kamal-skiff 0.2.0 → 0.5.0

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: cdb99cc1736f7ff3c6057f0617d784fb027850139f6e838469e1f1bde812c03a
4
- data.tar.gz: e3600a4d93fc6e3eb60761c6a7684394ed10319ce4a947027cf7681f99544b02
3
+ metadata.gz: b8e59e20b087bcae677641f4f8e1061dc9c7d2b2c4cceb00cd41fd597b8e7252
4
+ data.tar.gz: c6e3c1840db9d1ac8344be6ae13659fbb0ff05c1763a98836b302347a182cc50
5
5
  SHA512:
6
- metadata.gz: bcda624fab93d5a02dc361c1587108a2bbd4db39c1d605e87da71253a82e7fdddacda37461a989fc523d3c1cea440ca741e08516ff74fbefee4af26eaf1e6587
7
- data.tar.gz: 8dd01d371bdc2851d8777301c87cbefc305745b75b8c6f572ad6a1c83c072d2b272ab8f598a9a21ccbdb3095ea0d11c8046a8cdac97a6ff2ab6d1cbc776117fc
6
+ metadata.gz: 6e85dd1dbea08e3a8cb821a6583e9f67b62a59faba8dc49020c2cfaa045265546a654b82481fac2e0426a7db9658181c4a1e7a3caca0fd2e5eb4fa7fa3337ffb
7
+ data.tar.gz: 7d56f92e3fd93c1f45e92b9e7c86e53cb873ee51f8b88caf971fa31ea89e23439905ac6e72f79cbfa30f73e5d913dc3003ee03ec3a674bbda2e2dd51783b0c0b
data/README.md CHANGED
@@ -2,44 +2,74 @@
2
2
 
3
3
  Skiff uses [Kamal](https://kamal-deploy.org) to deploy static sites using nginx with Server-Side Includes (SSI).
4
4
 
5
- ## Local development
5
+ Understand the why and the how in this introduction video: https://www.youtube.com/watch?v=YoabUEzpM6k
6
+
7
+ ## Setting up your first Skiff site
8
+
9
+ 1. Create a new site scaffold and enter the project:
10
+ ```sh
11
+ skiff new mysite
12
+ cd mysite
13
+ ```
6
14
 
7
- If you have a Ruby environment available, you can install Skiff globally with:
15
+ 2. Add your site files under `public/` (for example, `public/index.html` and includes in `public/_includes/`).
8
16
 
9
- ```sh
10
- gem install kamal-skiff
11
- ```
17
+ 3. Put the site in a Git repository and push it to GitHub, since the server auto-pulls from git:
18
+ ```sh
19
+ git init
20
+ git add .
21
+ git commit -m "Initial site"
22
+ git branch -M master
23
+ git remote add origin git@github.com:username/repo.git
24
+ git push -u origin master
25
+ ```
12
26
 
13
- Then run `skiff dev` to start the development server.
27
+ 4. Set `GIT_URL` in `.kamal/secrets` so the server can pull your repository (relying on ENV GITHUB_TOKEN):
28
+ ```bash
29
+ GIT_URL=https://x-access-token:${GITHUB_TOKEN}@github.com/username/repo.git
30
+ ```
14
31
 
15
- ...otherwise, you can run a dockerized version via an alias (add this to your .bashrc or similar to simplify re-use). On macOS, use:
32
+ ### If you need to create a GitHub access token
16
33
 
17
- ```sh
18
- alias skiff-dev="docker build -t skiff-site . && docker run -it --rm -p 4000:80 -v ./public:/site/public --name skiff-site skiff-site nginx '-g daemon off;'"
19
- alias skiff="docker run -it --rm -v '${PWD}:/workdir' -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock -e SSH_AUTH_SOCK='/run/host-services/ssh-auth.sock' -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/basecamp/kamal-skiff:latest"
20
- ```
34
+ - Go to **GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens**.
35
+ - Direct link: https://github.com/settings/tokens?type=beta
36
+ - Click **Generate new token** and configure:
37
+ - **Token name**: A descriptive name (e.g., `mysite-deploy`)
38
+ - **Expiration**: Choose an appropriate duration
39
+ - **Repository access**: Select "Only select repositories" → choose your site's repository
40
+ - **Permissions**: Repository permissions → **Contents**: `Read-only`
41
+ - Click **Generate token** and copy the value.
42
+ - Store the token in 1Password:
43
+ - Use the **Deploy** vault
44
+ - Create or update an item for your site (e.g., `mysite.do`)
45
+ - Add the token as a field named `GITHUB_TOKEN`
21
46
 
22
- Then run `skiff-dev` to start the development server, and use `skiff [command]` for everything else.
47
+ 5. Update `config/deploy.yml` with your server address in `servers` and confirm the `image` name.
23
48
 
24
- ## Deploying the site for the first time
49
+ Kamal 2 uses a local registry by default (`registry.server: localhost:5555`), so you do not need to configure remote registry credentials unless you change that setting.
25
50
 
26
- First ensure that you've set `GIT_URL` to a repository address with a valid access token embedded in the `.env` file. This access token must have access to pull from the git repository in question (see [personal access tokens for GitHub](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) for an example).
51
+ 6. Deploy your site:
52
+ ```sh
53
+ skiff deploy
54
+ ```
27
55
 
28
- Then you must also setup an access token for your Docker image repository (see [Create and manage access tokens for Docker Hub](https://docs.docker.com/security/for-developers/access-tokens/) for an example).
56
+ This will install Docker on your server (using `apt-get`) if it is not already available.
29
57
 
30
- Finally, you must add the server address into `config/deploy.yml`, and ensure that the image and repository configurations are correct.
58
+ If you're upgrading an existing site from Kamal 1, run `kamal upgrade` once (and `kamal upgrade -d staging` for staging) before your next `skiff deploy`.
59
+
60
+ ## Local development
31
61
 
32
- Now you're ready to run `skiff deploy` to deploy your site to the server. This will install Docker on your server (using `apt-get`), if it isn't already available.
62
+ Run `skiff dev` to start the development server on localhost:4000.
33
63
 
34
64
  ## Deploying changes to production
35
65
 
36
- Changes checked into git are automatically pulled onto the Skiff server every 10 seconds. So all you have to do is checkin your changes and push them.
66
+ Changes checked into git are automatically pulled onto the Skiff server every 10 seconds. So all you have to do is check in your changes and push them.
37
67
 
38
- If you need to change the nginx configuration in `config/server.conf`, make your changes to that file, check them into git and push, and then run `skiff restart` to test the configuration file and restart the server if it's valid.
68
+ If you need to change the nginx configuration in `config/server.conf`, make your changes to that file, check them into git, and push. Skiff will detect the update, validate the new config, and reload nginx automatically.
39
69
 
40
70
  ## Deploying changes to staging first
41
71
 
42
- To use a staging server, you must set `GIT_BRANCH` in .env to the branch you're using for staging. Then you can deploy the site to a staging server using `skiff deploy --staging`, which will use the configuration in `config/deploy.staging.yml`, and start pulling updates from the branch specified.
72
+ To use a staging server, set `GIT_BRANCH` in `config/deploy.staging.yml` under `env.clear` to the branch you're using for staging. Then you can deploy the site to a staging server using `skiff deploy --staging`, which will use the configuration in `config/deploy.staging.yml`, and start pulling updates from the branch specified.
43
73
 
44
74
  ## Flushing etag caches after changing include files
45
75
 
data/lib/skiff/cli.rb CHANGED
@@ -50,7 +50,7 @@ class Skiff::Cli < Thor
50
50
  desc "refresh", "Force pull latest changes from git"
51
51
  option :staging, aliases: "-s", type: :boolean, default: false, desc: "On staging server"
52
52
  def refresh
53
- kamal_exec 'git checkout -f & git pull \$GIT_URL'
53
+ kamal_exec 'cd /tmp/repo && git fetch --depth 1 origin ${GIT_BRANCH:-HEAD} && git reset --hard FETCH_HEAD && rsync -a --delete --exclude=config/ --exclude=serve /tmp/repo/ /site/'
54
54
  end
55
55
 
56
56
  desc "logs", "Follow logs from server"
@@ -1,8 +1,8 @@
1
1
  FROM nginx:latest
2
2
 
3
- # Install git to provide polling updates
3
+ # Install git and rsync to provide polling updates
4
4
  RUN apt-get update -qq && \
5
- apt-get install --no-install-recommends -y git && \
5
+ apt-get install --no-install-recommends -y git rsync && \
6
6
  rm -rf /var/lib/apt/lists /var/cache/apt/archives
7
7
 
8
8
  # Site lives here
@@ -13,24 +13,26 @@ gem install kamal-skiff
13
13
  ...otherwise, you can run a dockerized version via an alias (add this to your .bashrc or similar to simplify re-use). On macOS, use:
14
14
 
15
15
  ```sh
16
- alias skiff="docker run -it --rm -v '${PWD}:/workdir' -v '/run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock' -e SSH_AUTH_SOCK='/run/host-services/ssh-auth.sock' -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/basecamp/kamal-skiff:latest"
16
+ alias skiff='docker run -it --rm -v "${PWD}:/workdir" -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock -e SSH_AUTH_SOCK="/run/host-services/ssh-auth.sock" -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/basecamp/kamal-skiff:latest'
17
17
  ```
18
18
 
19
19
  Then run `skiff dev` to start the development server.
20
20
 
21
21
  ## Deploying changes to production (or staging)
22
22
 
23
- Changes checked into git are automatically pulled onto the Skiff server every 10 seconds. So all you have to do is checkin your changes and push them.
23
+ Changes checked into git are automatically pulled onto the Skiff server every 10 seconds. So all you have to do is check in your changes and push them.
24
24
 
25
- If you need to change the nginx configuration in `config/server.conf`, make your changes to that file, check them into git and push, and then run `skiff restart` to test the configuration file and restart the server if it's valid.
25
+ If you need to change the nginx configuration in `config/server.conf`, make your changes to that file, check them into git, and push. Skiff will detect the update, validate the new config, and reload nginx automatically.
26
26
 
27
27
  ## Deploying the site for the first time
28
28
 
29
- First ensure that you've set `GIT_URL` to a repository address with a valid access token embedded in the `.env` file. This access token must have access to pull from the git repository in question (see [personal access tokens for GitHub](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) for an example).
29
+ If this site was originally deployed with Kamal 1, run `kamal upgrade` once (and `kamal upgrade -d staging` for staging) before your next `skiff deploy`.
30
30
 
31
- Then you must also setup an access token for your Docker image repository (see [Create and manage access tokens for Docker Hub](https://docs.docker.com/security/for-developers/access-tokens/) for an example).
31
+ First ensure that you've set `GIT_URL` to a repository address with a valid access token embedded in `.kamal/secrets`. This access token must have access to pull from the git repository in question (see [personal access tokens for GitHub](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) for an example).
32
32
 
33
- Finally, you must add the server address into `config/deploy.yml`, and ensure that the image and repository configurations are correct.
33
+ Kamal 2 uses a local registry by default (`registry.server: localhost:5555`), so you do not need to configure remote registry credentials unless you change that setting.
34
+
35
+ Finally, you must add the server address into `config/deploy.yml`, and ensure that the image configuration is correct.
34
36
 
35
37
  Now you're ready to run `skiff deploy` to deploy your site to the server. This will install Docker on your server (using `apt-get`), if it isn't already available.
36
38
 
@@ -1,4 +1,4 @@
1
- # Deploy your site to a staging server with skiff stage
1
+ # Deploy your site to a staging server with skiff deploy --staging
2
2
  servers:
3
3
  - 192.168.0.2
4
4
 
@@ -8,25 +8,18 @@ image: <%= @user_name %>/<%= @site_name %>
8
8
  servers:
9
9
  - 192.168.0.1
10
10
 
11
- # Use GIT_URL from env to auto-update site via git pulls.
12
- # Remember to run `kamal env push` after making changes!
11
+ # Use GIT_URL from secrets to auto-update site via git pulls.
13
12
  env:
14
13
  secret:
15
14
  - GIT_URL
16
15
 
17
- # Credentials for your image host.
16
+ # Use Kamal's local registry.
18
17
  registry:
19
- # Specify the registry server, if you're not using Docker Hub
20
- # server: registry.digitalocean.com / ghcr.io / ...
21
- username: <%= @user_name %>
18
+ server: localhost:5555
22
19
 
23
- # Always use an access token rather than real password when possible.
24
- password:
25
- - SKIFF_REGISTRY_PASSWORD
26
-
27
- # Check /up against 80
28
- healthcheck:
29
- port: 80
20
+ proxy:
21
+ healthcheck:
22
+ path: /up
30
23
 
31
24
  # Use a different ssh user than root
32
25
  # ssh:
@@ -19,7 +19,7 @@ server {
19
19
  error_page 404 /_errors/404.html;
20
20
 
21
21
  # Folders starting with _ are not publicly accessible
22
- location ~ ^/_$ {
22
+ location ~ ^/_ {
23
23
  internal;
24
24
  }
25
25
 
@@ -1,2 +1,6 @@
1
- # Ignore env file
1
+ # Ignore local secrets
2
+ /.kamal/secrets*
2
3
  /.env
4
+
5
+ # Ignore git directory (clone fresh at runtime to avoid layer caching issues)
6
+ /.git
@@ -1,2 +1,2 @@
1
- # Ignore env file
1
+ /.kamal/secrets*
2
2
  /.env
@@ -0,0 +1 @@
1
+ GIT_URL=https://x-access-token:YOUR_TOKEN@github.com/<%= @user_name %>/<%= @site_name %>.git
@@ -1,17 +1,117 @@
1
1
  #!/bin/bash
2
- set -e
2
+ set -eo pipefail
3
+
4
+ REPO_DIR=/tmp/repo
5
+ SITE_DIR=/site
6
+
7
+ log() {
8
+ if [ $# -gt 0 ]; then
9
+ echo "⛵ [skiff] $*"
10
+ else
11
+ sed 's/^/⛵ [skiff] /'
12
+ fi
13
+ }
14
+
15
+ sync_continuously() {
16
+ sleep 5 # Wait for nginx
3
17
 
4
- polling_pull() {
5
18
  while true; do
6
- echo "Pulling latest..."
7
- git checkout -f || true
8
- git pull $GIT_URL $GIT_BRANCH || true
19
+ if sync; then
20
+ log "Synced."
21
+ else
22
+ log "Error during sync, will retry..."
23
+ fi
24
+
9
25
  sleep 10
10
26
  done
11
27
  }
12
28
 
13
- # When GIT_URL is set start polling in the background
14
- [[ "$GIT_URL" ]] && polling_pull &
29
+ sync() {
30
+ sync_site_assets && sync_server_conf
31
+ }
32
+
33
+ sync_site_assets() {
34
+ log "Fetching ${GIT_BRANCH:-HEAD}..."
35
+
36
+ if [ -d "$REPO_DIR/.git" ]; then
37
+ # Subsequent runs: fetch and check for changes
38
+ cd "$REPO_DIR"
39
+ OLD_HEAD=$(git rev-parse HEAD)
40
+ git fetch --depth 1 origin "${GIT_BRANCH:-HEAD}" 2>&1 | log
41
+
42
+ # Skip sync if no changes
43
+ if [ "$OLD_HEAD" = "$(git rev-parse FETCH_HEAD)" ]; then
44
+ log "Already up to date."
45
+ return 0
46
+ fi
47
+ git reset --hard FETCH_HEAD 2>&1 | log
48
+ else
49
+ # First run: shallow clone
50
+ rm -rf "$REPO_DIR"
51
+ git clone --depth 1 ${GIT_BRANCH:+--branch "$GIT_BRANCH"} "$GIT_URL" "$REPO_DIR" 2>&1 | log
52
+ fi
53
+
54
+ # Sync to site
55
+ rsync -a --delete --exclude='config/' --exclude='serve' "$REPO_DIR/" "$SITE_DIR/"
56
+ }
57
+
58
+ sync_server_conf() {
59
+ local repo_dir="$REPO_DIR/config"
60
+ local site_dir="$SITE_DIR/config"
61
+ local backup_dir="$SITE_DIR/config/.bak"
62
+ local changed=false
63
+
64
+ mkdir -p "$site_dir"
65
+
66
+ for repo_conf in "$repo_dir"/*.conf; do
67
+ [ -f "$repo_conf" ] || continue
68
+ local name=$(basename "$repo_conf")
69
+ local site_conf="$site_dir/$name"
70
+
71
+ if [ -f "$site_conf" ] && cmp -s "$repo_conf" "$site_conf"; then
72
+ continue
73
+ fi
74
+
75
+ changed=true
76
+ break
77
+ done
78
+
79
+ [ "$changed" = true ] || return 0
80
+
81
+ log "Detected change to config/*.conf, validating and reloading nginx..."
82
+
83
+ # Back up current config files
84
+ rm -rf "$backup_dir"
85
+ mkdir -p "$backup_dir"
86
+ for f in "$site_dir"/*.conf; do
87
+ [ -f "$f" ] && cp "$f" "$backup_dir/"
88
+ done
89
+
90
+ # Copy new config files
91
+ for repo_conf in "$repo_dir"/*.conf; do
92
+ [ -f "$repo_conf" ] && cp "$repo_conf" "$site_dir/"
93
+ done
94
+
95
+ if nginx -t 2>&1 | log && nginx -s reload 2>&1 | log; then
96
+ rm -rf "$backup_dir"
97
+ log "Reloaded nginx with updated config."
98
+ return 0
99
+ else
100
+ # Restore backup
101
+ if [ -d "$backup_dir" ]; then
102
+ for f in "$backup_dir"/*.conf; do
103
+ [ -f "$f" ] && cp "$f" "$site_dir/"
104
+ done
105
+ rm -rf "$backup_dir"
106
+ log "Reverted config to last known good version."
107
+ fi
108
+
109
+ log "Config changed, but nginx could not be restarted."
110
+ return 1
111
+ fi
112
+ }
113
+
15
114
 
16
- # Start NGINX in the foreground
115
+ # Start continuously syncing in background if GIT_URL is set
116
+ [[ "$GIT_URL" ]] && sync_continuously &
17
117
  nginx -g 'daemon off;'
@@ -1,4 +1,5 @@
1
- template "dotfiles/env.tt", ".env"
1
+ empty_directory ".kamal"
2
+ template "dotfiles/kamal-secrets.tt", ".kamal/secrets"
2
3
  copy_file "dotfiles/gitignore", ".gitignore"
3
4
  copy_file "dotfiles/dockerignore", ".dockerignore"
4
5
 
data/lib/skiff/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Skiff
2
- VERSION = "0.2.0"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,29 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kamal-skiff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-10-26 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: kamal
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - ">="
16
+ - - "~>"
18
17
  - !ruby/object:Gem::Version
19
- version: '1.0'
18
+ version: '2.0'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
- - - ">="
23
+ - - "~>"
25
24
  - !ruby/object:Gem::Version
26
- version: '1.0'
25
+ version: '2.0'
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: thor
29
28
  requirement: !ruby/object:Gem::Requirement
@@ -80,7 +79,6 @@ dependencies:
80
79
  - - ">="
81
80
  - !ruby/object:Gem::Version
82
81
  version: '0'
83
- description:
84
82
  email: dhh@hey.com
85
83
  executables:
86
84
  - skiff
@@ -98,8 +96,8 @@ files:
98
96
  - lib/skiff/templates/config/deploy.yml.tt
99
97
  - lib/skiff/templates/config/server.conf
100
98
  - lib/skiff/templates/dotfiles/dockerignore
101
- - lib/skiff/templates/dotfiles/env.tt
102
99
  - lib/skiff/templates/dotfiles/gitignore
100
+ - lib/skiff/templates/dotfiles/kamal-secrets.tt
103
101
  - lib/skiff/templates/public/_errors/404.html
104
102
  - lib/skiff/templates/public/_includes/footer.html
105
103
  - lib/skiff/templates/public/_includes/header.html
@@ -112,7 +110,6 @@ homepage: https://github.com/basecamp/kamal-skiff
112
110
  licenses:
113
111
  - MIT
114
112
  metadata: {}
115
- post_install_message:
116
113
  rdoc_options: []
117
114
  require_paths:
118
115
  - lib
@@ -127,8 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
124
  - !ruby/object:Gem::Version
128
125
  version: '0'
129
126
  requirements: []
130
- rubygems_version: 3.4.20
131
- signing_key:
127
+ rubygems_version: 4.0.3
132
128
  specification_version: 4
133
129
  summary: Deploy static sites using nginx + SSI with Kamal.
134
130
  test_files: []
@@ -1,2 +0,0 @@
1
- SKIFF_REGISTRY_PASSWORD=YOUR_TOKEN
2
- GIT_URL=https://YOUR_TOKEN:@github.com/<%= @user_name %>/<%= @site_name %>.git