standard-procedure-anvil 0.2.0 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +16 -82
- data/assets/cloudinit/dokku.yml +149 -11
- data/assets/cloudinit/redis.yml +4 -1
- data/checksums/standard-procedure-anvil-0.2.1.gem.sha512 +1 -0
- data/checksums/standard-procedure-anvil-0.2.3.gem.sha512 +1 -0
- data/docs/app.md +51 -0
- data/docs/cloudinit.md +33 -0
- data/docs/configuration.md +7 -0
- data/docs/roadmap.md +12 -0
- data/docs/ruby-on-rails.md +69 -0
- data/docs/secrets.md +20 -0
- data/docs/why.md +17 -0
- data/lib/anvil/app/host_deployer.rb +2 -0
- data/lib/anvil/app/host_installer.rb +4 -2
- data/lib/anvil/app.rb +7 -1
- data/lib/anvil/cloudinit/generator.rb +2 -25
- data/lib/anvil/cloudinit.rb +3 -2
- data/lib/anvil/version.rb +1 -1
- metadata +12 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 98f86509b143ec7364ce16bf3b13a407b68e18d75c4baa98772eebe2b553fb85
|
4
|
+
data.tar.gz: a6e71d4b0e94a329ec786144ffa195df6d7308631619f9accffe5d22589988fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6c629afa2f500c15226489eb66a9161b7538c097e5533a5640df42cde9d87a21a8709ab2d9b088cb0f5c293c976cb3f25fbe9db606d765c63a13c6a798614e7
|
7
|
+
data.tar.gz: 40a298d3fdf5e6880395524824ec62350c57ac6ee0e36cff15aea0d12211b974ed098f56e1d65861c8774ffebba5a44c0cd78559046eb13edafddcf407a76839
|
data/CHANGELOG.md
CHANGED
@@ -3,3 +3,23 @@
|
|
3
3
|
## [0.1.0] - 2023-06-19
|
4
4
|
|
5
5
|
- Initial release
|
6
|
+
|
7
|
+
## [0.2.0] - 2023-07-05
|
8
|
+
|
9
|
+
- It works for me
|
10
|
+
Successfully deployed a number of apps into production using this
|
11
|
+
|
12
|
+
## [0.2.1] - 2023-07-06
|
13
|
+
|
14
|
+
- Corrected dokku proxy SSL settings
|
15
|
+
- Tidy up of various bits of code and configuration
|
16
|
+
|
17
|
+
## [0.2.2] - 2023-08-14
|
18
|
+
|
19
|
+
- Updated the redis cloudinit file to use the latest version from Redis, instead of the older one that is included with Ubuntu.
|
20
|
+
|
21
|
+
## [0.2.3] - 2024-01-17
|
22
|
+
|
23
|
+
- Updaetd the dokku cloudinit file to install dokku and docker from the official repositories
|
24
|
+
- Added support for %{HOSTNAME} in cloudinit files
|
25
|
+
- Improved reliability when reading configuration files
|
data/README.md
CHANGED
@@ -2,110 +2,44 @@
|
|
2
2
|
|
3
3
|
Some simple scripts for installing [Dokku](https://dokku.com) applications on Ubuntu servers.
|
4
4
|
|
5
|
+
## Why does this exist?
|
6
|
+
|
7
|
+
I needed a tool to [simplify the management](/docs/why.md) of my many dokku-deployed Ruby on Rails apps.
|
8
|
+
|
5
9
|
## Installation
|
6
10
|
|
11
|
+
Anvil requires Ruby 2.7 or newer, as it uses ConcurrentRuby to handle doing more than one thing at once.
|
12
|
+
|
7
13
|
```ruby
|
8
14
|
gem install standard-procedure-anvil
|
9
15
|
```
|
10
16
|
|
11
17
|
## Usage
|
12
18
|
|
13
|
-
###
|
19
|
+
### Build a server
|
14
20
|
|
15
21
|
Ultimately the plan is to use [Fog](https://github.com/fog/fog) to handle building servers.
|
16
22
|
|
17
23
|
But until then, you can prepare your servers using [CloudInit](https://cloudinit.readthedocs.io/en/latest/)
|
18
24
|
|
19
|
-
|
20
|
-
|
21
|
-
So firstly we ask Anvil which cloudinit configurations it has available:
|
22
|
-
|
23
|
-
```sh
|
24
|
-
anvil cloudinit list
|
25
|
-
```
|
26
|
-
|
27
|
-
This will give us a list of prewritten cloud init scripts - of which dokku is probably the one we're most interested in.
|
28
|
-
|
29
|
-
Next we tell anvil to generate our configuration:
|
30
|
-
|
31
|
-
```sh
|
32
|
-
anvil cloudinit generate dokku --user app --public-key ~/.ssh/my_key.pub > ~/Desktop/my_server.yml
|
33
|
-
```
|
34
|
-
|
35
|
-
Anvil generates a dokku configuration (and places it on our desktop) that will create an Ubuntu 22.04 box with docker and dokku preinstalled. Plus it will create a user called `app` that can log in through SSH using a public key `my_key.pub`. The server itself is locked down so only ports 80, 443 and 22 are open, only the users `app` and `dokku` are allowed to log in and they must use public/private key encryption - no passwords allowed.
|
36
|
-
|
37
|
-
To test this, it's worth taking a look at [Multipass](https://multipass.run) - a tool from Canonical that lets you create virtual machines (using cloud init files) on your local machine - meaning you can try out various configurations without spending money at a hosting company.
|
38
|
-
|
39
|
-
Once you've built a preconfigured virtual machine, we can move on to getting our dokku application installed.
|
40
|
-
|
41
|
-
### Installing an application onto the server
|
42
|
-
|
43
|
-
Move to your application's root folder and create the deploy.yml file (see below). Then use the `app install` command to set dokku up for your first deployment.
|
44
|
-
|
45
|
-
```sh
|
46
|
-
anvil app install
|
47
|
-
```
|
48
|
-
|
49
|
-
This will SSH into the server (or servers if you have multiple) from your config file and:
|
50
|
-
|
51
|
-
- Installs any dokku plugins that you have specified
|
52
|
-
- Tells dokku to create the app
|
53
|
-
- Uses your config file to set the environment variables for the app
|
54
|
-
- Sets some sensible defaults for Nginx and makes sure it proxies correctly to your app
|
55
|
-
- Optionally forwards the correct SSL/TLS headers if your app is behind a load-balancer
|
56
|
-
- Finally it runs the post-installation scripts from your config file, which you can use to configure your plugins
|
25
|
+
[Generating a cloudinit file](/docs/cloudinit.md) with `anvil cloudinit generate`
|
57
26
|
|
58
|
-
|
27
|
+
### Install and deploy
|
59
28
|
|
60
|
-
|
61
|
-
anvil app deploy
|
62
|
-
```
|
63
|
-
As this is the first deployment, anvil will create git remotes for each host, then do the initial git push. If you have multiple servers configured, these should run in parallel (coming soon). Once each deployment has completed, anvil will SSH in, scale your app and run the post-first-deployment scripts.
|
64
|
-
|
65
|
-
You can then use the same `anvil app deploy` command to deploy the app again - but as it knows this isn't the first deployment (as it does not need to create the git remotes), it will run your post-deployment scripts (not post-first-deployment) each time.
|
66
|
-
|
67
|
-
To change the number of processes (as defined by your Procfile), you can set the `scale` key(s) in your config file and then call:
|
68
|
-
|
69
|
-
```sh
|
70
|
-
anvil app scale
|
71
|
-
```
|
72
|
-
|
73
|
-
(COMING SOON)
|
74
|
-
Finally, if you need to change the values of any environment variables, update your config file and use:
|
75
|
-
|
76
|
-
```sh
|
77
|
-
anvil app configure
|
78
|
-
```
|
79
|
-
|
80
|
-
### Configuration Files
|
81
|
-
|
82
|
-
An Anvil configuration file specifies the configuration for multiple servers and multiple apps. Each server is configured, then each app is installed onto each server.
|
29
|
+
Use the `anvil app install` and `anvil app deploy` commands to [install and deploy](/docs/app.md) your app to your server.
|
83
30
|
|
84
|
-
|
31
|
+
### Manage and reconfigure
|
85
32
|
|
86
|
-
|
33
|
+
Use `anvil app scale` and `anvil app reconfigure` to manage and reconfigure your app. (Docs coming soon)
|
87
34
|
|
88
|
-
|
35
|
+
### Ruby on Rails
|
89
36
|
|
90
|
-
|
91
|
-
|
92
|
-
The secrets are just extra environment variables that are added to the ones defined in your config file - in the format:
|
93
|
-
|
94
|
-
```
|
95
|
-
SECRET1=VALUE1 SECRET2=VALUE2
|
96
|
-
```
|
97
|
-
|
98
|
-
You can either specify `--secrets my-secrets-file.env` to load these from a separate file. Or you can load them from stdin.
|
99
|
-
|
100
|
-
For example, I use [Bitwarden](https://bitwarden.com) as my password locker and use the Bitwarden CLI to access my secrets. The CLI is installed through homebrew, I then authenticate and can use a command like:
|
101
|
-
|
102
|
-
```sh
|
103
|
-
bw get notes secrets@myapp.com | anvil app install deploy.myapp.yml -S
|
104
|
-
```
|
105
|
-
I have the environment variables for myapp.com stored in Bitwarden as a secure note with the title "secrets@myapp.com". So `bw get notes secrets@myapp.com` loads them from my vault and pipes them to the `anvil app install` command. The anvil command is using the `-S` (or `--secrets-stdin`) option which means it will read the information piped in by bitwarden. So, once decrypted, the confidential data never touches a disk until it gets written into the dokku app configuration on the server.
|
37
|
+
I'm a Rails developer and I built anvil to help me with my Rails apps. Here are [some things I learnt along the way](/docs/ruby-on-rails.md).
|
106
38
|
|
107
39
|
## Contributing
|
108
40
|
|
41
|
+
Check out the [Roadmap](/docs/roadmap.md)
|
42
|
+
|
109
43
|
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/standard-procedure-anvil.
|
110
44
|
|
111
45
|
## License
|
data/assets/cloudinit/dokku.yml
CHANGED
@@ -1,4 +1,146 @@
|
|
1
1
|
#cloud-config
|
2
|
+
apt:
|
3
|
+
sources:
|
4
|
+
source_dokku:
|
5
|
+
source: 'deb https://packagecloud.io/dokku/dokku/ubuntu/ $RELEASE main'
|
6
|
+
key: |
|
7
|
+
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
8
|
+
Version: GnuPG v1.4.11 (GNU/Linux)
|
9
|
+
|
10
|
+
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
|
69
|
+
=laU4
|
70
|
+
-----END PGP PUBLIC KEY BLOCK-----
|
71
|
+
source_docker:
|
72
|
+
source: 'deb [arch=amd64] https://download.docker.com/linux/ubuntu $RELEASE stable'
|
73
|
+
key: |
|
74
|
+
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
75
|
+
|
76
|
+
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
|
133
|
+
YT90qFF93M3v01BbxP+EIY2/9tiIPbrd
|
134
|
+
=0YYh
|
135
|
+
-----END PGP PUBLIC KEY BLOCK-----
|
136
|
+
|
137
|
+
debconf_selections:
|
138
|
+
vhost: dokku dokku/vhost_enable boolean true
|
139
|
+
# set the domain name of the new Dokku server
|
140
|
+
hostname: dokku dokku/hostname string %
|
141
|
+
# this copies over the public SSH key assigned to the server
|
142
|
+
key: dokku dokku/key_file string /home/ubuntu/.ssh/authorized_keys
|
143
|
+
|
2
144
|
users:
|
3
145
|
- name: %{USER}
|
4
146
|
groups: users, admin, docker
|
@@ -6,6 +148,7 @@ users:
|
|
6
148
|
shell: /bin/bash
|
7
149
|
ssh_authorized_keys:
|
8
150
|
- %{PUBLIC_KEY}
|
151
|
+
|
9
152
|
packages:
|
10
153
|
- fail2ban
|
11
154
|
- ufw
|
@@ -15,24 +158,19 @@ packages:
|
|
15
158
|
- curl
|
16
159
|
- gpg-agent
|
17
160
|
- software-properties-common
|
161
|
+
- dokku
|
162
|
+
|
18
163
|
package_update: true
|
19
164
|
package_upgrade: true
|
165
|
+
package_reboot_if_required: true
|
166
|
+
|
20
167
|
runcmd:
|
21
168
|
# General server setup
|
22
169
|
- timedatectl set-timezone UTC
|
23
170
|
- echo "${USER}:${USER}" | chpasswd
|
24
|
-
#
|
25
|
-
- sudo install -m 0755 -d /etc/apt/keyrings
|
26
|
-
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
27
|
-
- sudo chmod a+r /etc/apt/keyrings/docker.gpg
|
28
|
-
- echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
29
|
-
# Install docker
|
30
|
-
- apt-get update
|
31
|
-
- apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
32
|
-
# Install dokku
|
33
|
-
- echo "dokku dokku/vhost_enable boolean true" | sudo debconf-set-selections
|
34
|
-
- wget https://dokku.com/install/v0.30.7/bootstrap.sh && sudo DOKKU_TAG=v0.30.7 bash bootstrap.sh
|
171
|
+
# Setup dokku
|
35
172
|
- cat /home/app/.ssh/authorized_keys | dokku ssh-keys:add admin
|
173
|
+
- dokku domains:set-global %{HOSTNAME}
|
36
174
|
- dokku git:set --global deploy-branch main
|
37
175
|
# Fail2Ban setup
|
38
176
|
- printf "[sshd]\nenabled = true\nbanaction = iptables-multiport" > /etc/fail2ban/jail.local
|
data/assets/cloudinit/redis.yml
CHANGED
@@ -34,11 +34,14 @@ runcmd:
|
|
34
34
|
- sed -i -e '/^\(#\|\)AuthorizedKeysFile/s/^.*$/AuthorizedKeysFile .ssh\/authorized_keys/' /etc/ssh/sshd_config
|
35
35
|
- sed -i '$a AllowUsers %{USER}' /etc/ssh/sshd_config
|
36
36
|
# Set up Redis
|
37
|
+
- curl -fsSL https://packages.redis.io/gpg | gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
|
38
|
+
- echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/redis.list
|
39
|
+
- apt-get update
|
37
40
|
- apt-get -y install redis-server
|
38
41
|
- sed -i 's/supervised no/supervised systemd/g' /etc/redis/redis.conf
|
39
42
|
- sed -i 's/bind 127.0.0.1 ::1/# bind 127.0.0.1 ::1/g' /etc/redis/redis.conf
|
40
43
|
- sed -i 's/protected-mode yes/protected-mode no/g' /etc/redis/redis.conf
|
41
|
-
- systemctl restart redis.service
|
44
|
+
- systemctl restart redis-server.service
|
42
45
|
- |
|
43
46
|
cat > /etc/logrotate.d/redis-server << EOF
|
44
47
|
/var/log/redis/redis-server*.log {
|
@@ -0,0 +1 @@
|
|
1
|
+
2b56322e96127aa43986eaa2de436eafd64c7d5260d61db1a13605d95bf0fc3b331f006c0b534d845c05e781659518f37d3f8aa17475e6e926675d5ea1985a50
|
@@ -0,0 +1 @@
|
|
1
|
+
c6b89e5ee248e5d0209eee59b5e9445faced31aa2c9ea77a4229bdf9d93cccfbdd29ce88819eb9774e161e6e46b8ebe884f0e3680908279c1dc5f26417d23e6b
|
data/docs/app.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# The `app` command
|
2
|
+
|
3
|
+
## Installing an application
|
4
|
+
|
5
|
+
Move to your application's root folder and create the deploy.yml file (see below). Then use the `app install` command to set dokku up for your first deployment.
|
6
|
+
|
7
|
+
```sh
|
8
|
+
anvil app install
|
9
|
+
```
|
10
|
+
|
11
|
+
This will SSH into the server (or servers if you have multiple) from your config file and:
|
12
|
+
|
13
|
+
- Installs any dokku plugins that you have specified
|
14
|
+
- Tells dokku to create the app
|
15
|
+
- Uses your config file to set the environment variables for the app
|
16
|
+
- Sets some sensible defaults for Nginx and makes sure it proxies correctly to your app
|
17
|
+
- Optionally forwards the correct SSL/TLS headers if your app is behind a load-balancer
|
18
|
+
- Finally it runs the post-installation scripts from your config file, which you can use to configure your plugins
|
19
|
+
|
20
|
+
## Deploying an application
|
21
|
+
|
22
|
+
Next up we deploy the app.
|
23
|
+
|
24
|
+
```sh
|
25
|
+
anvil app deploy
|
26
|
+
```
|
27
|
+
As this is the first deployment, anvil will create git remotes for each host, then do the initial git push. If you have multiple servers configured, these should run in parallel (coming soon). Once each deployment has completed, anvil will SSH in, scale your app and run the post-first-deployment scripts.
|
28
|
+
|
29
|
+
You can then use the same `anvil app deploy` command to deploy the app again - but as it knows this isn't the first deployment (as it does not need to create the git remotes), it will run your post-deployment scripts (not post-first-deployment) each time.
|
30
|
+
|
31
|
+
To change the number of processes (as defined by your Procfile), you can set the `scale` key(s) in your config file and then call:
|
32
|
+
|
33
|
+
```sh
|
34
|
+
anvil app scale
|
35
|
+
```
|
36
|
+
|
37
|
+
(COMING SOON)
|
38
|
+
Finally, if you need to change the values of any environment variables, update your config file and use:
|
39
|
+
|
40
|
+
```sh
|
41
|
+
anvil app configure
|
42
|
+
```
|
43
|
+
|
44
|
+
## Configuration files
|
45
|
+
|
46
|
+
The [anvil configuration file](/docs/configuration.md) is the heart of the system.
|
47
|
+
|
48
|
+
## Secrets
|
49
|
+
|
50
|
+
You don't want to store your secrets (passwords, encryption keys) in your anvil configuration. Instead anvil can [read your secrets](/docs/secrets.md) from a separate file or from the command line.
|
51
|
+
|
data/docs/cloudinit.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Building a server
|
2
|
+
|
3
|
+
## Cloudinit
|
4
|
+
|
5
|
+
A [CloudInit](https://cloudinit.readthedocs.io/en/latest/) file is a YML file that you load into a virtual machine while it is being created. As the server boots, uses the cloudinit configuration to install software and set itself up. With most cloud hosting providers, you will find an option for "user data", or something similar, on the "create a new server" page.
|
6
|
+
|
7
|
+
### Generate a configuration
|
8
|
+
|
9
|
+
So firstly we ask Anvil which cloudinit configurations it has available:
|
10
|
+
|
11
|
+
```sh
|
12
|
+
anvil cloudinit list
|
13
|
+
```
|
14
|
+
|
15
|
+
This will give us a list of prewritten cloud init scripts - of which dokku is probably the one we're most interested in.
|
16
|
+
|
17
|
+
Next we tell anvil to generate our configuration:
|
18
|
+
|
19
|
+
```sh
|
20
|
+
anvil cloudinit generate dokku --user app --public-key ~/.ssh/my_key.pub > ~/Desktop/my_server.yml
|
21
|
+
```
|
22
|
+
|
23
|
+
Anvil generates a dokku configuration (and places it on our desktop) that will create an Ubuntu 22.04 box with docker and dokku preinstalled. Plus it will create a user called `app` that can log in through SSH using a public key `my_key.pub`. The server itself is locked down so only ports 80, 443 and 22 are open, only the users `app` and `dokku` are allowed to log in and they must use public/private key encryption - no passwords allowed.
|
24
|
+
|
25
|
+
### Testing your configuration
|
26
|
+
|
27
|
+
To test this, it's worth taking a look at [Multipass](https://multipass.run) - a tool from Canonical that lets you create virtual machines (using cloud init files) on your local machine. This means you can try out various configurations without spending money at a hosting company.
|
28
|
+
|
29
|
+
One thing to note when using multipass - it requires SSH access for a user called "ubuntu". So take your generated cloudinit file, locate the SSH configuration section and the "AllowUsers" line - and add the "ubuntu" user to it. Something like: ` - sed -i '$a AllowUsers %{USER} ubuntu dokku' /etc/ssh/sshd_config`.
|
30
|
+
|
31
|
+
Multipass has its own private key generated for the ubuntu user, and uses this to manage the server. Of course, the multipass VM is only on your machine, plus its private key is hidden away, so it's not a security risk. But in general `anvil cloudinit generate` disallows all SSH access apart from your named user (using your own key), and the `dokku` user if applicable.
|
32
|
+
|
33
|
+
Once you've built a preconfigured virtual machine, we can move on to getting our dokku application installed. However, note that it can take several minutes for the initialisation process to complete - so don't start your deployment too early, or your server won't be ready and will reboot whilst your setting things up.
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Anvil configuration files
|
2
|
+
|
3
|
+
An Anvil configuration file specifies the configuration for multiple servers and multiple apps. Each server is configured, then each app is installed onto each server.
|
4
|
+
|
5
|
+
For now take a look at the two samples in the spec folder - [single-server](/spec/fixtures/single-server.config.yml) and [multi-server](/spec/fixtures/multi-server.config.yml).
|
6
|
+
|
7
|
+
Also check out the [tips for Ruby on Rails](/docs/ruby-on-rails.md) which has an example configuration file.
|
data/docs/roadmap.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# Roadmap
|
2
|
+
|
3
|
+
As I mentioned, this is pretty much designed for my own use.
|
4
|
+
|
5
|
+
There are a few bits I still need (which will be V1) and then I want to open it up. But if it gets too generic, you might as well just write a load of shell scripts to manage dokku yourself - it's important to keep it simple.
|
6
|
+
|
7
|
+
## To do
|
8
|
+
|
9
|
+
- [ ] `app reconfigure`
|
10
|
+
- [ ] Add `--first`/`--not-first` options to `app deploy` so you can override the first-deployment behaviour (in case you get a failure and need to re-run everything)
|
11
|
+
- [ ] Instead of relying on the ssh-agent, allow the use of your private key when connecting to servers
|
12
|
+
- [ ] Parallel execution across multiple hosts
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Dokku and Ruby on Rails
|
2
|
+
|
3
|
+
(incomplete - coming soon)
|
4
|
+
|
5
|
+
- If using the Mysql plugin, use the Mysql2 protocol
|
6
|
+
- store your RAILS_MASTER_KEY and SECRET_KEY_BASE outside of your configuration file (see [secrets](/docs/secrets.md))
|
7
|
+
- in your config/environments/production.rb or config/environments/staging.rb set `config.force_ssl = false` - dokku's nginx configuration will do the redirect for you if you're using the Let's Encrypt plugin, or you can set the redirect on your load-balancer. Setting `config.force_ssl = true` causes issues with the health checks
|
8
|
+
- Make sure your app knows its hostname; set it as an environment variable in your configuration file and then use that hostname in your environment file as follows: `config.action_mailer.default_url_options = {host: ENV["HOSTNAME"]}` and `Rails.application.routes.default_url_options[:host] = config.action_mailer.default_url_options[:host]`. This means that when you need to generate a full URL (as opposed to a relative path), Rails knows what to use.
|
9
|
+
- Use a CHECKS file that looks like this (again using that HOSTNAME environment variable), so dokku's zero-deployment checks can connect correctly. My `/health_check` route just returns a `200 OK` in most apps, but in some it actually checks the database connection, as well as some other services (although this causes problems with the initial deployment, which is why checks are switched off the first time through)
|
10
|
+
```
|
11
|
+
WAIT=10
|
12
|
+
ATTEMPTS=5
|
13
|
+
http://{{ var "HOSTNAME" }}/health_check
|
14
|
+
```
|
15
|
+
|
16
|
+
A typical Rails deploy.yml for a single-server, totally self-contained app, looks like this:
|
17
|
+
|
18
|
+
```yaml
|
19
|
+
version: 0.1
|
20
|
+
hosts:
|
21
|
+
- myapp.example.com:
|
22
|
+
user: app
|
23
|
+
app:
|
24
|
+
domain: myapp.example.com
|
25
|
+
port: 3000
|
26
|
+
environment:
|
27
|
+
- BUNDLE_WITHOUT=test:development
|
28
|
+
- CABLE_CHANNEL_PREFIX=myapp
|
29
|
+
- EMAIL_DOMAIN=mail.myapp.example.com
|
30
|
+
- EMAIL_HOST=smtp.myapp.example.com
|
31
|
+
- EMAIL_PORT=587
|
32
|
+
- EMAIL_USER=postmaster@mail.myapp.example.com
|
33
|
+
- HOSTNAME=myapp.example.com
|
34
|
+
- NODE_ENV=production
|
35
|
+
- RACK_ENV=production
|
36
|
+
- RAILS_ENV=production
|
37
|
+
- RAILS_LOG_TO_STDOUT=true
|
38
|
+
- RAILS_MAX_THREADS=10
|
39
|
+
- RAILS_SERVE_STATIC_FILES=true
|
40
|
+
resource_limit: 2048m
|
41
|
+
scale: web=2 worker=1
|
42
|
+
load_balancer: false
|
43
|
+
nginx:
|
44
|
+
client_max_body_size: 512m
|
45
|
+
proxy_read_timeout: 60s
|
46
|
+
plugins:
|
47
|
+
- cron-restart
|
48
|
+
- maintenance
|
49
|
+
- redis
|
50
|
+
- memcached
|
51
|
+
- mysql
|
52
|
+
- letsencrypt
|
53
|
+
scripts:
|
54
|
+
after_install:
|
55
|
+
- dokku cron-restart:set app schedule '0 3 * * *'
|
56
|
+
- dokku memcached:create memcached
|
57
|
+
- dokku memcached:link memcached app
|
58
|
+
- dokku redis:create redis_db
|
59
|
+
- dokku redis:link redis_db app
|
60
|
+
- dokku mysql:create mysql_db
|
61
|
+
- dokku config:set app MYSQL_DATABASE_SCHEME=mysql2
|
62
|
+
- dokku mysql:link mysql_db app
|
63
|
+
after_first_deploy:
|
64
|
+
- dokku letsencrypt:set app email me@myapp.example.com
|
65
|
+
- dokku letsencrypt:enable app
|
66
|
+
- dokku letsencrypt:cron-job --add
|
67
|
+
- dokku run app bin/rails db:seed
|
68
|
+
|
69
|
+
```
|
data/docs/secrets.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Secrets
|
2
|
+
|
3
|
+
Finally, you'll probably want to check your deploy.yml file into source control. But you _definitely_ don't want to be storing important secrets - database passwords, encryption keys and so on - where everyone can see them.
|
4
|
+
|
5
|
+
So the `anvil app` commands also allow you to specify secrets, either from another file, or via the command line.
|
6
|
+
|
7
|
+
The secrets are just extra environment variables that are added to the ones defined in your config file - in the format:
|
8
|
+
|
9
|
+
```
|
10
|
+
SECRET1=VALUE1 SECRET2=VALUE2
|
11
|
+
```
|
12
|
+
|
13
|
+
You can either specify `--secrets my-secrets-file.env` to load these from a separate file. Or you can load them from stdin.
|
14
|
+
|
15
|
+
For example, I use [Bitwarden](https://bitwarden.com) as my password locker and use the Bitwarden CLI to access my secrets. The CLI is installed through homebrew, I then authenticate and can use a command like:
|
16
|
+
|
17
|
+
```sh
|
18
|
+
bw get notes secrets@myapp.com | anvil app install deploy.myapp.yml -S
|
19
|
+
```
|
20
|
+
I have the environment variables for myapp.com stored in Bitwarden as a secure note with the title "secrets@myapp.com". So `bw get notes secrets@myapp.com` loads them from my vault and pipes them to the `anvil app install` command. The anvil command is using the `-S` (or `--secrets-stdin`) option which means it will read the information piped in by bitwarden. So, once decrypted, the confidential data never touches a disk until it gets written into the dokku app configuration on the server.
|
data/docs/why.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Why does this exist?
|
2
|
+
|
3
|
+
[Dokku](https://dokku.com) is great at installing and configuring containers on a single host.
|
4
|
+
|
5
|
+
But you do need to install dokku, generate your configuration and environment variables, install your plugins and app and then configure all those plugins.
|
6
|
+
|
7
|
+
Unfortunately, there's no [single configuration file](https://github.com/dokku/dokku/issues/1558) for dokku.
|
8
|
+
|
9
|
+
In addition, dokku is really designed for managing a single server. But I'm actually using it to manage multiple servers that are hidden behind a load-balancer.
|
10
|
+
|
11
|
+
So to manage this, I wanted a single configuration file that I could user for all my dokku information, that could then use that configuration across multiple servers.
|
12
|
+
|
13
|
+
Currently it's extremely tailored to my needs - it's built for Ubuntu 22.04, it creates a user called "app" (although you can change that), it names your dokku app "app".
|
14
|
+
|
15
|
+
I've also added in cloudinit configs for some of the other servers I have to use. Of course, these are not related to dokku, but anvil can generate them easily so it's useful to keep them all in one place.
|
16
|
+
|
17
|
+
There are several [limitations](/docs/roadmap.md) to how it works - it does what I need but does need expansion. That will come soon.
|
@@ -41,10 +41,12 @@ module Anvil
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def create_git_remote
|
44
|
+
logger.info "git remote add #{host} dokku@#{host}:/app"
|
44
45
|
logger.info `git remote add #{host} dokku@#{host}:/app`
|
45
46
|
end
|
46
47
|
|
47
48
|
def do_git_push
|
49
|
+
logger.info "git push #{host} #{branch}:main"
|
48
50
|
logger.info `git push #{host} #{branch}:main`
|
49
51
|
end
|
50
52
|
|
@@ -24,7 +24,7 @@ module Anvil
|
|
24
24
|
protected
|
25
25
|
|
26
26
|
def install_plugins ssh
|
27
|
-
(configuration_for_app.
|
27
|
+
(configuration_for_app.dig("plugins") || []).each do |plugin|
|
28
28
|
ssh.exec! "sudo dokku plugin:install https://github.com/dokku/dokku-#{plugin}.git #{plugin}"
|
29
29
|
end
|
30
30
|
end
|
@@ -40,7 +40,9 @@ module Anvil
|
|
40
40
|
def set_dokku_options ssh
|
41
41
|
ssh.exec! "dokku docker-options:add app run \"--add-host=host.docker.internal:host-gateway\"", "set_dokku_options"
|
42
42
|
ssh.exec! "dokku domains:set app #{configuration_for_app["domain"]}", "set_dokku_options"
|
43
|
-
ssh.exec! "dokku proxy:
|
43
|
+
ssh.exec! "dokku proxy:set app nginx", "set_dokku_options"
|
44
|
+
ssh.exec! "dokku ports:add app http:80:#{configuration_for_app["port"]}", "set_dokku_options"
|
45
|
+
ssh.exec! "dokku ports:add app https:443:#{configuration_for_app["port"]}", "set_dokku_options"
|
44
46
|
ssh.exec! "dokku nginx:set app client-max-body-size #{configuration_for_app["nginx"]["client_max_body_size"]}", "set_dokku_options"
|
45
47
|
ssh.exec! "dokku nginx:set app proxy-read-timeout #{configuration_for_app["nginx"]["proxy_read_timeout"]}", "set_dokku_options"
|
46
48
|
if configuration_for_app["load_balancer"]
|
data/lib/anvil/app.rb
CHANGED
@@ -14,6 +14,8 @@ module Anvil
|
|
14
14
|
long_desc <<-DESC
|
15
15
|
List the environment variables for an app (on a given host)
|
16
16
|
|
17
|
+
Normally you never need call this command directly as it is called by the install command.
|
18
|
+
|
17
19
|
Example:
|
18
20
|
anvil app env /path/to/config
|
19
21
|
|
@@ -42,6 +44,10 @@ module Anvil
|
|
42
44
|
If the /path/to/config is not supplied, it defaults to deploy.yml
|
43
45
|
|
44
46
|
If --secrets-stdin is specified then additional environment variable values will be read from STDIN, if --secrets=/path/to/secrets is specified then they will be read from the file specified. This is so you can specify environment variables that you do not want stored in source control. These should be formatted as "VAR=value VAR2=value2" etc.
|
47
|
+
|
48
|
+
password-manager read my-secrets | anvil app install /path/to/config --secrets-stdin
|
49
|
+
|
50
|
+
Alternatively you can specify secrets as a separate file using the --secrets option. Again, this should be formatted as "VAR=value VAR2=value2".
|
45
51
|
DESC
|
46
52
|
option :secrets, type: :string, default: nil, aliases: "-s"
|
47
53
|
option :secrets_stdin, type: :boolean, default: false, aliases: "-S"
|
@@ -84,7 +90,7 @@ module Anvil
|
|
84
90
|
def read_secrets(filename: nil, stdin: false)
|
85
91
|
return nil if filename.nil? && !stdin
|
86
92
|
return $stdin.read if stdin
|
87
|
-
|
93
|
+
File.read(filename) if File.exist?(filename)
|
88
94
|
end
|
89
95
|
end
|
90
96
|
end
|
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
module Anvil
|
4
4
|
class Cloudinit
|
5
|
-
class Generator < Struct.new(:filename, :user, :public_key_path)
|
5
|
+
class Generator < Struct.new(:filename, :user, :public_key_path, :hostname)
|
6
6
|
def call
|
7
7
|
public_key = public_key_path.to_s.gsub("~", Dir.home)
|
8
8
|
|
9
9
|
if File.exist?(public_key)
|
10
|
-
puts File.read(filename).gsub("%{USER}", user).gsub("%{PUBLIC_KEY}", File.read(public_key))
|
10
|
+
puts File.read(filename).gsub("%{USER}", user).gsub("%{HOSTNAME}", hostname).gsub("%{PUBLIC_KEY}", File.read(public_key))
|
11
11
|
else
|
12
12
|
puts "Cannot find public key file at #{public_key}"
|
13
13
|
end
|
@@ -15,26 +15,3 @@ module Anvil
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
18
|
-
|
19
|
-
# Compare this snippet from assets/cloudinit/mysql.ubuntu-22.yml:
|
20
|
-
# # frozen_string_literal: true
|
21
|
-
#
|
22
|
-
# ---
|
23
|
-
# packages:
|
24
|
-
# - mysql-server
|
25
|
-
# - mysql-client
|
26
|
-
# - libmysqlclient-dev
|
27
|
-
#
|
28
|
-
# users:
|
29
|
-
# - name: <%= user %>
|
30
|
-
# groups: sudo
|
31
|
-
# shell: /bin/bash
|
32
|
-
# sudo: ALL=(ALL) NOPASSWD:ALL
|
33
|
-
# ssh_authorized_keys:
|
34
|
-
# - <%= public_key %>
|
35
|
-
#
|
36
|
-
# files:
|
37
|
-
# - path: /etc/mysql/mysql.conf.d/mysqld.cnf
|
38
|
-
# content: |
|
39
|
-
# [mysqld]
|
40
|
-
# bind-address =
|
data/lib/anvil/cloudinit.rb
CHANGED
@@ -18,14 +18,15 @@ module Anvil
|
|
18
18
|
Generate a cloudinit configuration for a server
|
19
19
|
|
20
20
|
Example:
|
21
|
-
anvil cloudinit generate mysql.ubuntu-22 --user dbuser --public_key ~/.ssh/my_key.pub
|
21
|
+
anvil cloudinit generate mysql.ubuntu-22 --user dbuser --public_key ~/.ssh/my_key.pub --hostname myserver.com
|
22
22
|
|
23
23
|
DESC
|
24
24
|
option :user, type: :string, default: "app", aliases: "-u"
|
25
25
|
option :public_key, type: :string, default: "~/.ssh/id_rsa.pub", aliases: "-k"
|
26
|
+
option :hostname, type: :string, default: "example.com", aliases: "-h"
|
26
27
|
def generate configuration
|
27
28
|
filename = File.dirname(__FILE__) + "/../../assets/cloudinit/#{configuration}.yml"
|
28
|
-
Anvil::Cloudinit::Generator.new(filename, options[:user], options[:public_key]).call
|
29
|
+
Anvil::Cloudinit::Generator.new(filename, options[:user], options[:public_key], options[:hostname]).call
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
data/lib/anvil/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: standard-procedure-anvil
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rahoul Baruah
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -121,6 +121,15 @@ files:
|
|
121
121
|
- checksums/standard-procedure-anvil-0.1.6.gem.sha512
|
122
122
|
- checksums/standard-procedure-anvil-0.1.7.gem.sha512
|
123
123
|
- checksums/standard-procedure-anvil-0.2.0.gem.sha512
|
124
|
+
- checksums/standard-procedure-anvil-0.2.1.gem.sha512
|
125
|
+
- checksums/standard-procedure-anvil-0.2.3.gem.sha512
|
126
|
+
- docs/app.md
|
127
|
+
- docs/cloudinit.md
|
128
|
+
- docs/configuration.md
|
129
|
+
- docs/roadmap.md
|
130
|
+
- docs/ruby-on-rails.md
|
131
|
+
- docs/secrets.md
|
132
|
+
- docs/why.md
|
124
133
|
- exe/anvil
|
125
134
|
- lib/anvil.rb
|
126
135
|
- lib/anvil/app.rb
|
@@ -171,7 +180,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
171
180
|
- !ruby/object:Gem::Version
|
172
181
|
version: '0'
|
173
182
|
requirements: []
|
174
|
-
rubygems_version: 3.4.
|
183
|
+
rubygems_version: 3.4.22
|
175
184
|
signing_key:
|
176
185
|
specification_version: 4
|
177
186
|
summary: Tools for managing servers and apps built using dokku
|