shippy 0.2.8 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1fe36006872a9b130eecbfa26b391a3a645dafaced62917c530ac9510944abd8
4
- data.tar.gz: a8c0268d4cdb6c776600a21038eeb5de722c7601a770a8f33630bb8b414f0fc6
3
+ metadata.gz: c8a547859425588ab2d87d11010d8650d8b1d5ee67b6abe1239aa1215c8799ed
4
+ data.tar.gz: bab2f41d53d11eda45e4e7e70d09bda20e09d2ca6d239a1d0985c3d796a62766
5
5
  SHA512:
6
- metadata.gz: 7b70994648b3f4c7c842460b335faf0f9a70ae62fff47a3236bcf145d052d45a189c05bddf72cbc1be14ce692f854366df846b925fa248a7ca841c65354a7340
7
- data.tar.gz: abd35fa707247d73707c3c41ec15e5f65cb46d01a386aa48a7c003f92640b341ccb3cfd229224e03c759dcdf064cf2cfd960663bc0af79c085ea866897a51dd5
6
+ metadata.gz: c44eaa3a47d6e8c13c43d41a4fc676e9c9347459c15ef7c4e44ed134c9b99e15d8dfcb6934a82313b1840c7ee69ad450555890de26cd8b4ac94f436ea0daff79
7
+ data.tar.gz: 534231ef52cb40213a44c969f53c4f479f6573a5a299c3a03ac5327ba2be4a2e8dec1591ccc56c4ae5f5c85d96c87c41b3274c09d5139242adf727999eb373c1
data/README.md CHANGED
@@ -2,14 +2,17 @@
2
2
 
3
3
  Shippy is a lightweight container orchestration tool designed specifically for homelabs. It combines the simplicity of Docker Compose with a powerful Ruby DSL, inspired by the deployment workflows of Capistrano and Kamal.
4
4
 
5
- ## Features
5
+ ## ✨ Features
6
6
 
7
- - Ruby DSL to generate the docker-compose YAML files
8
- - Centralized source to define secrets
9
- - Uses Traefik as a reverse proxy with SSL wildcard support
10
- - Manage the entire lab with a local `bin/shippy` command.
7
+ - Ruby DSL to generate cleaner, DRYer docker-compose.yml files.
8
+ - Server bootstrapping to automatically provision a raw server with Docker and necessary dependencies.
9
+ - Built-in rollbacks to afely revert to previous deployments with a single command.
10
+ - Immutable deployments which automatically pins image digests (sha256) during deployment to prevent upstream changes from breaking your apps.
11
+ - Centralized secrets for securely defining and injecting encrypted credentials.
12
+ - First-class Traefik support comes as a built-in reverse proxy routing with SSL wildcard certificate generation.
13
+ - Garbage collection which defines prune commands to keep your homelab server's storage clean.
11
14
 
12
- ## 🚀 Getting Started
15
+ ## 🚀 Getting started
13
16
 
14
17
  Install the gem:
15
18
 
@@ -17,7 +20,7 @@ Install the gem:
17
20
  $ gem install shippy
18
21
  ```
19
22
 
20
- In you homelab directory execute:
23
+ Make your homelab directory:
21
24
 
22
25
  ```shell
23
26
  home$ mkdir homelab && cd homelab
@@ -29,6 +32,48 @@ This creates the core structure:
29
32
  - `config/`: Shippy configuration and secrets.
30
33
  - `bin/shippy`: Your local entry point for all commands.
31
34
 
35
+ ### đŸ› ī¸ Provision & deploy
36
+
37
+ Shippy can automatically prepare a brand new Ubuntu/Debian server for you. Once your `config/shippy.yml` is configured with your host IP and SSH details, run:
38
+
39
+ ```shell
40
+ homelab$ bin/shippy setup
41
+ ```
42
+
43
+ This command will:
44
+
45
+ - Log into your server and install `curl`, `docker.io`, and `docker-compose` via `apt-get` (if missing).
46
+ - Create the required directory structures (`apps/` and `backups/`).
47
+ - Deploy all of your configured apps.
48
+
49
+ ### đŸ•šī¸ CLI commands & app management
50
+
51
+ Shippy features both global commands (for the whole lab) and granular commands (for specific apps).
52
+
53
+ Global commands:
54
+
55
+ - `bin/shippy deploy` - Deploys or updates all applications in your `apps/` directory.
56
+ - `bin/shippy stop` - Stops all applications.
57
+ - `bin/shippy refresh` - Pulls the latest images and restarts all services.
58
+ - `bin/shippy prune all` - Cleans up unused images (older than 7 days) and stopped containers (older than 3 days).
59
+
60
+ Granular app commands (`bin/shippy app <command> <name>`):
61
+
62
+ - `bin/shippy app deploy proxy` - Deploys only the `proxy` app.
63
+ - `bin/shippy app logs proxy --follow` - Tails the logs for the proxy app.
64
+ - `bin/shippy app restart proxy --service traefik` - Restarts only the specific traefik service inside the proxy app.
65
+ - `bin/shippy app status proxy` - Shows the current ps status of the app's containers.
66
+ - `bin/shippy app compile proxy` - Generates the files that would be copied to the server in the `builds/apps/proxy/` directory, useful for debugging the files without actually deploying them.
67
+
68
+ ### âĒ Instant rollbacks
69
+
70
+ Because Shippy backs up your previous deployment directories (configurable via `keep_releases`), you can easily roll back if an update breaks your app:
71
+
72
+ ```shell
73
+ # Rollback the proxy app by 1 version
74
+ bin/shippy app rollback proxy -n 1
75
+ ```
76
+
32
77
  ### Docker compose DSL:
33
78
 
34
79
  Conventions:
@@ -76,6 +121,173 @@ By running `bin/shippy deploy proxy` the DSL gets converted to YAML and deployed
76
121
 
77
122
  See the examples directory for more options.
78
123
 
124
+ ### âš™ī¸ Configuration
125
+
126
+ Shippy uses a central configuration file (located at `config/shippy.yml`) to define your lab environment.
127
+
128
+ #### Global Settings
129
+
130
+ Here is an example configuration:
131
+
132
+ ```yaml
133
+ host: 'homelab.local'
134
+ ssh:
135
+ user: name
136
+ wildcard_domain: 'lab.example.com'
137
+ deploy_to: '/var/lib/homelab'
138
+ secrets_file: 'config/secrets.yml.enc'
139
+ keep_releases: 5
140
+ media_path: '/media/storage'
141
+ ```
142
+
143
+ Shippy is designed to automatically secure your services with a wildcard SSL certificate (`*.lab.example.com`). To achieve this, it relies on a `DNS-01` challenge.
144
+
145
+ * You must use Cloudflare as your DNS provider so Traefik can automatically verify domain ownership via their API.
146
+ * You need to configure a wildcard DNS record (`*.lab.example.com`) in Cloudflare pointing to the IP address of your homelab server.
147
+
148
+ #### Secrets management
149
+
150
+ Your secrets are stored in an encrypted file defined by secrets_file (e.g., `config/secrets.yml.enc`).
151
+
152
+ Secrets in this file are scoped to the specific app they belong to. For example, if you have an app named `proxy`, your secrets file structure should look like this:
153
+
154
+ ```yaml
155
+ proxy:
156
+ cloudflare_email: "user@example.com"
157
+ cloudflare_token: "your-api-token"
158
+ ```
159
+
160
+ Inside your `apps/proxy/docker-compose.rb`, calling `secrets(:cloudflare_email)` will fetch the value specifically nested under the proxy key. This ensures services only have access to their own credentials.
161
+
162
+ Run `bin/shippy secrets edit` to safely modify them using your default `$EDITOR`.
163
+
164
+ âš ī¸ Secrets are only encrypted at rest within the `config/secrets.yml.enc` file. During compilation and deployment, these secrets are injected as plaintext into the generated `docker-compose.yml` files and will be visible in your local `builds/` directory. The primary intent of this feature is to allow you to safely commit your homelab configuration to Git without exposing keys in your repository, not to provide strict, enterprise-grade runtime security. There is an open issue to integrate natively with Docker Compose secrets [here](https://gitlab.com/mrbobin/shippy/-/issues/1).
165
+
166
+ #### đŸšĻ Exposing Apps (Traefik)
167
+
168
+ To make an app accessible from the outside world, use the `use_traefik` helper inside your service block.
169
+
170
+ ```ruby
171
+ use_traefik(name: 'home-assistant', port: 8123)
172
+ ```
173
+
174
+ This automatically generates the labels required to expose the container at `home-assistant.lab.example.com`.
175
+
176
+ - The name dictates the subdomain.
177
+ - The port is optional if your container only exposes a single port, but it __should be explicitly defined__ if the container exposes multiple internal ports.
178
+
179
+ Sometimes you need more complex routing than just matching the host. You can pass a block to use_traefik to append custom Traefik routing rules.
180
+
181
+ ```ruby
182
+ use_traefik(name: 'matrix', port: 80) do |rule|
183
+ "#{rule} && PathPrefix(`/.well-known/`)"
184
+ end
185
+ ```
186
+
187
+ If a single container provides multiple web interfaces (like MinIO, which has an API and a web console), you can manually build and append the Traefik labels using `build_traefik_labels`:
188
+
189
+ ```ruby
190
+ labels do
191
+ all_labels = ["traefik.enable=true"]
192
+ all_labels += build_traefik_labels(name: :minio, port: 9000)
193
+ all_labels += build_traefik_labels(name: :mconsole, port: 9001)
194
+
195
+ all_labels
196
+ end
197
+ ```
198
+
199
+ #### 🎛 Overriding defaults
200
+
201
+ To keep your files clean, Shippy provides a `use_default_option`s method. Calling this automatically applies default Docker networks for Traefik access, a standard restart policy (like `unless-stopped`), and default logging limits so your drives don't fill up.
202
+
203
+ If you need fine-grained control, you can omit `use_default_options` and specify exactly what you want:
204
+
205
+ ```ruby
206
+ networks { [ 'backend', 'lan_access' ] } # 'lan_access' is required by Traefik(if used on the service)
207
+ use_default_restart
208
+ use_default_logging
209
+ ```
210
+
211
+ This is highly useful when placing an app on an isolated network without exposing it to the default network.
212
+
213
+ #### Post-deployment hooks
214
+
215
+ Sometimes a container needs to run commands immediately after it boots up (like database migrations or setting up initial admin users). You can define an array of commands in a `hooks` block, and Shippy will execute them sequentially inside the running container:
216
+
217
+ ```ruby
218
+ hooks do
219
+ [
220
+ 'bundle exec rails db:create',
221
+ 'bundle exec rails db:migrate'
222
+ ]
223
+ end
224
+ ```
225
+
226
+ #### DRY service configurations
227
+
228
+ Shippy allows you to define custom helper methods directly inside the `Shippy.define` block to share logic across multiple services.
229
+
230
+ - Use `x.<key>` to access variables from your global config file (like `x.media_path`).
231
+ - Use `app.<method_name>` to call your custom methods from inside a service block.
232
+
233
+ ```ruby
234
+ Shippy.define do
235
+ # 1. Define a shared helper method
236
+ def nextcloud_volumes
237
+ [
238
+ # 'x' accesses properties from your global config file
239
+ "#{x.media_path}/nextcloud/html:/var/www/html",
240
+ "#{x.media_path}/nextcloud/apps:/var/www/html/custom_apps",
241
+ "#{x.media_path}/nextcloud/config:/var/www/html/config",
242
+ "#{x.media_path}/nextcloud/data:/var/www/html/data",
243
+ "#{x.media_path}/nextcloud/themes:/var/www/html/themes"
244
+ ]
245
+ end
246
+
247
+ service :nextcloud do
248
+ image { 'nextcloud:fpm-alpine' }
249
+
250
+ # 2. Call the helper method using 'app'
251
+ volumes { app.nextcloud_volumes }
252
+ end
253
+
254
+ service :nextcloud_proxy do
255
+ image { 'nginx:alpine' }
256
+ depends_on { ['nextcloud'] }
257
+
258
+ # 3. Combine unique volumes with the shared volumes array
259
+ volumes { ["./nginx/nginx.conf:/etc/nginx/nginx.conf"] + app.nextcloud_volumes }
260
+ use_traefik(name: 'box')
261
+ end
262
+ end
263
+ ```
264
+
265
+ #### App files & ERB templating
266
+
267
+ Any files or directories you place inside an app's directoy (alongside `docker-compose.rb`) are automatically copied over to your homelab server during deployment. This makes it incredibly easy to bundle configuration files (like Nginx confs, Prometheus rules, or Traefik configs) right next to the service that uses them.
268
+
269
+ However, there are two crucial rules to understand about how Shippy handles these files:
270
+
271
+ 1. Avoid bind mounting to the app directory
272
+ Because Shippy keeps track of your deployment history (using the `keep_releases` setting in your config), the actual directory where your app runs gets rotated and moved to a backups path on every deploy. Do not use relative bind mounts for data that changes or needs to persist (e.g., `./data:/var/lib/mysql`). When you deploy again, the folder moves, and your container will start with a fresh, empty directory! Always bind mount your persistent data to a stable, absolute path on your server, such as the `media_path` defined in your `shippy.yml`, or use standard Docker named volumes.
273
+
274
+ 2. ERB templating for dynamic configs
275
+ Shippy allows you to use Ruby's ERB templating inside your supplemental files. If you need to inject secrets, loop through configurations, or access global variables, simply append `.erb` to the file name.
276
+ During deployment, Shippy will evaluate the Ruby code, strip the `.erb` extension, and upload the fully rendered file to your server.
277
+
278
+ Example: `apps/proxy/traefik/config.yml.erb` In this Traefik config, we can securely inject the Cloudflare email right from our encrypted `secrets.yml.enc` file:
279
+
280
+ ```yaml
281
+ certificatesResolvers:
282
+ ssl-resolver:
283
+ acme:
284
+ # Shippy dynamically injects this secret during deploy!
285
+ email: <%= secrets(:cloudflare_email) %>
286
+ storage: /etc/traefik/acme/acme.json
287
+ dnsChallenge:
288
+ provider: cloudflare
289
+ ```
290
+
79
291
  ## Development
80
292
 
81
293
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -2,7 +2,6 @@ host: 'homelab.local'
2
2
  ssh:
3
3
  user: root
4
4
  wildcard_domain: 'local.homelab.com'
5
- local_domain: local
6
5
  deploy_to: '/var/lib/homelab'
7
6
  secrets_file: 'config/secrets.yml.enc'
8
7
  keep_releases: 10
@@ -52,7 +52,7 @@ module Shippy
52
52
  end
53
53
 
54
54
  delegate :x, to: Shippy
55
- delegate :wildcard_domain, :local_domain, to: :x
55
+ delegate :wildcard_domain, to: :x
56
56
 
57
57
  private
58
58
 
@@ -96,7 +96,7 @@ module Shippy
96
96
  end
97
97
 
98
98
  delegate :x, to: Shippy
99
- delegate :wildcard_domain, :local_domain, to: :x
99
+ delegate :wildcard_domain, to: :x
100
100
 
101
101
  def hooks
102
102
  if block_given?
@@ -1,3 +1,3 @@
1
1
  module Shippy
2
- VERSION = "0.2.8"
2
+ VERSION = "0.2.9"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shippy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.2.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marius Bobin