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 +4 -4
- data/README.md +50 -20
- data/lib/skiff/cli.rb +1 -1
- data/lib/skiff/templates/Dockerfile +2 -2
- data/lib/skiff/templates/README.md.tt +8 -6
- data/lib/skiff/templates/config/deploy.staging.yml +1 -1
- data/lib/skiff/templates/config/deploy.yml.tt +6 -13
- data/lib/skiff/templates/config/server.conf +1 -1
- data/lib/skiff/templates/dotfiles/dockerignore +5 -1
- data/lib/skiff/templates/dotfiles/gitignore +1 -1
- data/lib/skiff/templates/dotfiles/kamal-secrets.tt +1 -0
- data/lib/skiff/templates/serve +108 -8
- data/lib/skiff/templates/site.rb +2 -1
- data/lib/skiff/version.rb +1 -1
- metadata +8 -12
- data/lib/skiff/templates/dotfiles/env.tt +0 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b8e59e20b087bcae677641f4f8e1061dc9c7d2b2c4cceb00cd41fd597b8e7252
|
|
4
|
+
data.tar.gz: c6e3c1840db9d1ac8344be6ae13659fbb0ff05c1763a98836b302347a182cc50
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
|
|
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
|
-
|
|
15
|
+
2. Add your site files under `public/` (for example, `public/index.html` and includes in `public/_includes/`).
|
|
8
16
|
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
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
|
-
|
|
32
|
+
### If you need to create a GitHub access token
|
|
16
33
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
47
|
+
5. Update `config/deploy.yml` with your server address in `servers` and confirm the `image` name.
|
|
23
48
|
|
|
24
|
-
|
|
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
|
-
|
|
51
|
+
6. Deploy your site:
|
|
52
|
+
```sh
|
|
53
|
+
skiff deploy
|
|
54
|
+
```
|
|
27
55
|
|
|
28
|
-
|
|
56
|
+
This will install Docker on your server (using `apt-get`) if it is not already available.
|
|
29
57
|
|
|
30
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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=
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
|
@@ -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
|
|
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
|
-
#
|
|
16
|
+
# Use Kamal's local registry.
|
|
18
17
|
registry:
|
|
19
|
-
|
|
20
|
-
# server: registry.digitalocean.com / ghcr.io / ...
|
|
21
|
-
username: <%= @user_name %>
|
|
18
|
+
server: localhost:5555
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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:
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
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
|
data/lib/skiff/templates/serve
CHANGED
|
@@ -1,17 +1,117 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
set -
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
14
|
-
|
|
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
|
|
115
|
+
# Start continuously syncing in background if GIT_URL is set
|
|
116
|
+
[[ "$GIT_URL" ]] && sync_continuously &
|
|
17
117
|
nginx -g 'daemon off;'
|
data/lib/skiff/templates/site.rb
CHANGED
data/lib/skiff/version.rb
CHANGED
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.
|
|
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:
|
|
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: '
|
|
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: '
|
|
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:
|
|
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: []
|