Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/visualitypl/kamal-workshops-app
This is an app for 2024 workshops "Deploy with Kamal: A Hands-On Workshop"
https://github.com/visualitypl/kamal-workshops-app
Last synced: 2 days ago
JSON representation
This is an app for 2024 workshops "Deploy with Kamal: A Hands-On Workshop"
- Host: GitHub
- URL: https://github.com/visualitypl/kamal-workshops-app
- Owner: visualitypl
- Created: 2024-06-19T16:53:10.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2024-07-18T20:34:56.000Z (5 months ago)
- Last Synced: 2024-12-20T07:52:14.577Z (5 days ago)
- Language: Ruby
- Size: 92.8 KB
- Stars: 0
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# README
This is a simple Rails 7.1 application built based on Rails "blog app" guide.
We will be using this app to learn how to deploy a Rails app to VPS with Kamal.Sources:
- [Rails Guides](https://guides.rubyonrails.org/getting_started.html#creating-the-blog-application)
- [Kamal](https://kamal-deploy.org/)Pre-requisites:
- Ruby 3.3.4
- installed and configured git
- installed and configured ssh
- ssh-key without passphrase
- docker installed and updated# Workshop instructions
## 1. Sign up to the Companion app at kamal.cklos.foo
## 2 Clone the blog-space and install Kamal
```
git clone [email protected]:visualitypl/kamal-workshops-app.git
git clone https://github.com/visualitypl/kamal-workshops-app.gitgem install kamal
```## 3 Task 1 - Application with postgres
Example files for this task:
- [deploy.yml.example-1](config/deploy.yml.example-1)
- [.env.example-1](.env.example-1)### 3.1 Add kamal to blog-space
```
kamal init
```### 3.2 Setup deploy.yml
We will need to edit:
- service (name of the app: blog-space)
- image (#{Docker Hub username from the companion app}/#{name of the app})
- servers (IP from the companion app)
- registry (username: #{Docker Hub username from the companion app})
- env (clear, secret)
- builder (remote: [arch: amd64, host: #{from the companion app}])### 3.3 Setup .env
We will need to edit:
- KAMAL_REGISTRY_PASSWORD (Docker Hub token from the companion app)
- SECRET_KEY_BASE (generate secret key base with `rails secret`)
- POSTGRES_PASSWORD (pick a password)### 3.4 Setup docker-setup kamal hook
We will need to rename docker-setup.sample to docker-setup
in .kamal/hooks/ directory### 3.5 Deploy
To prepare docker on hosts, push env, deploy postgres accessory and deploy the app we need to run:
```shell
kamal server bootstrap
kamal env push
kamal accessory boot postgres
kamal deploy
```Alternatively, you can run command that calls all the above:
```shell
kamal setup
```### 3.6 Check the result
To check the result, run:
```shell
kamal audit
kamal details
```Visit the app at http://#{IP}
## 4 Task 2 - Adding redis and sidekiq
Example files for this task:
- [deploy.yml.example-2](config/deploy.yml.example-2)
- [.env.example-2](.env.example-2)### 4.1 Add sidekiq to deploy.yml
Add "worker" role to servers (save IP as web)
```yaml
servers:
worker:
hosts:
- 255.255.255.100 ## CHANGE ME
cmd: bundle exec sidekiq
options:
network: "kamal"
```### 4.2 Set Sidekiq as ActiveJob backend
We will need to edit `config/environments/production.rb` and `config/environments/staging.rb`
```ruby
config.active_job.queue_adapter = :sidekiq
```### 4.3 Add redis to deploy.yml
Add "redis" accessory
```yaml
accessories:
redis:
image: "redis:7.2-alpine"
roles:
- web
directories:
- data:/data
options:
network: "kamal"
cmd: "redis-server --requirepass <%= File.read('.env')[/REDIS_PASSWORD="(.*?)"/, 1] %>"
```### 4.4 Add Redis env vars to .env
Add two env vars to `.env`:
- REDIS_PASSWORD (pick a password)
- REDIS_URL (`"redis://:@blog-space-redis:6379/0"`, substitute the password with above)### 4.5 Reference REDIS_URL in deploy.yml
Add `REDIS_URL` to `env` section of deploy.yml
```yaml
env:
secret:
- SECRET_KEY_BASE
- POSTGRES_PASSWORD
- REDIS_URL
```### 4.6 Use Redis as ActiveCable backend
Edit `config/cable.yml` and set `adapter: redis` on production and staging
```yaml
staging:
adapter: redis
url: <%= ENV.fetch("REDIS_URL", "") %>
channel_prefix: blog_space_productionproduction:
adapter: redis
url: <%= ENV.fetch("REDIS_URL", "") %>
channel_prefix: blog_space_production
```
### 4.7 Commit the changes```shell
git add -A
git commit -m "Add redis and sidekiq"
```### 4.8 Push env vars to the server
```shell
kamal env push
```### 4.9 Start redis accessory and deploy the app
```shell
kamal accessory boot redis
kamal deploy
```### 4.10 Check the result
To check the result, run:
```shell
kamal audit
kamal details
```Visit the app at http://#{IP}
## 5. Deploy staging destination
Example files for this task:
- [deploy.staging.yml.example](config/deploy.staging.yml.example)
- [.env.staging.example](.env.staging.example)### 5.1 Add config for staging destination
Create `config/deploy.staging.yml`.
We only need to override values from `config/deploy.yml` that are different for staging.```yaml
servers:
web:
hosts:
- [HOST IP] ## CHANGE MEworker:
hosts:
- [HOST IP] ## CHANGE MEenv:
clear:
RAILS_ENV: "staging"
POSTGRES_DB: "blog_space_staging"accessories:
postgres:
files:
- "config/init.staging.sql:/docker-entrypoint-initdb.d/init.sql"redis:
cmd: "redis-server --requirepass <%= File.read('.env.staging')[/REDIS_PASSWORD="(.*?)"/, 1] %>"
```### 5.2 Add env vars for staging destination
Create `.env.staging` and add:
- SECRET_KEY_BASE (generate secret key base with `rails secret`)
- POSTGRES_PASSWORD (pick a password)
- REDIS_PASSWORD (pick a password)
- REDIS_URL (`"redis://:@blog-space-redis:6379/0"`, substitute the password with above)Notice that we are not setting `KAMAL_REGISTRY_PASSWORD` env var, because we are using the same one as in production.
### 5.3 Deploy
To use kamal with staging destination we need to pass `-d staging` flag to all commands.
Like before we need to setup docker on hosts, push env, deploy postgres accessory and deploy the app.```shell
kamal setup -d staging
``````shell
kamal server bootstrap -d staging
kamal env push -d staging
kamal accessory boot all -d staging
kamal deploy -d staging
```### 5.4 Check the result
To check the result, run:
```shell
kamal audit -d staging
kamal details -d staging
```Visit the app at http://#{STAGING-IP}
## 6. Breaking and fixing
### 6.1 Breaking
We will break the app by generating a migration that will fail.
```shell
bundle exec rails generate migration addAuthorToArticle
``````ruby
class AddAuthorToArticle < ActiveRecord::Migration[7.1]
def change
add_column :articles, :author, :string, null: false
end
end
```Commit the changes and push them to the server.
```shell
git add -A
git commit -m "Add author to article"
kamal deploy
```Inspect the output of the deploy command and notice that
the app have not been deployed to the server.### 6.2 Breaking even more
Fix the migration by adding a default value to the author column.
BUT at the same time break something else.```ruby
class AddAuthorToArticle < ActiveRecord::Migration[7.1]
def change
add_column :articles, :author, :string, null: false, default: ""
end
end
```Comment the "delete_barons_comments" route in `config/routes.rb`
```ruby
# post "delete_barons_comments", on: :member
```Commit the changes and push them to the server.
This time the migration were applied to the database.
But "the core functionality" of the app is lost.### 6.3 The Rollback
Rollback to previous version of the app:
```shell
kamal rollback# to find the version run:
kamal audit
```### 6.4 Cleanup
Remove the migration that we added previously.
This task has no solution here ;)