kamal-skiff 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5962234770cd990a7c673bf5a77b007bdda292e3a1fa0280c512da53de47cc70
4
+ data.tar.gz: 1bdbc85dcba5c4ac35f1f06b670d94ed0623298b3e266aff5e8d7c8a9379dec2
5
+ SHA512:
6
+ metadata.gz: 6105a3cd3883ee27ec8d32fea07d7ebb5833066bb4302260d8dc15dcc794cbfe6aaafcfb1a2665c612fa5adecad7bf1a9eb1b87113ddbbab9cacb8d4d3b18e61
7
+ data.tar.gz: 1d4ce26e94e4d1462f7522dca52f12b6d7da305e7696d34c84b6221af90ee85f7ede4460acb1308f5637353cf72a784af9d6f43778b7ccee606871168b14777f
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2023 37signals
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # Skiff
2
+
3
+ Skiff uses [Kamal](https://kamal-deploy.org) to deploy static sites using nginx with Server-Side Includes (SSI).
4
+
5
+ ## Local development
6
+
7
+ If you have a Ruby environment available, you can install Skiff globally with:
8
+
9
+ ```sh
10
+ gem install kamal-skiff
11
+ ```
12
+
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
+
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"
17
+ ```
18
+
19
+ Then run `skiff dev` to start the development server.
20
+
21
+ ## Deploying the site for the first time
22
+
23
+ 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).
24
+
25
+ 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).
26
+
27
+ Finally, you must add the server address into `config/deploy.yml`, and ensure that the image and repository configurations are correct.
28
+
29
+ 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.
30
+
31
+ ## Deploying changes to production
32
+
33
+ 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.
34
+
35
+ 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.
36
+
37
+ ## Deploying changes to staging first
38
+
39
+ 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.
40
+
41
+ ## Flushing etag caches after changing include files
42
+
43
+ Skiff uses [Server Side Includes](https://nginx.org/en/docs/http/ngx_http_ssi_module.html), which can change independently of your individual HTML files. When that happens, the caching etags for those latter files will not be updated automatically to reflect the change. You can run `skiff flush` to touch all the public HTML files, which will flush the etag cache.
44
+
45
+ ## License
46
+
47
+ Skiff is released under the [MIT License](https://opensource.org/licenses/MIT).
data/bin/skiff ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Prevent failures from being reported twice.
4
+ Thread.report_on_exception = false
5
+
6
+ require "kamal-skiff"
7
+
8
+ begin
9
+ Skiff::Cli.start(ARGV)
10
+ rescue => e
11
+ puts " \e[31mERROR (#{e.class}): #{e.message}\e[0m"
12
+ puts e.backtrace if ENV["VERBOSE"]
13
+ exit 1
14
+ end
@@ -0,0 +1,5 @@
1
+ module Skiff
2
+ end
3
+
4
+ require "skiff/cli"
5
+ require "skiff/version"
data/lib/skiff/cli.rb ADDED
@@ -0,0 +1,92 @@
1
+ require "thor"
2
+
3
+ class Skiff::Cli < Thor
4
+ include Thor::Actions
5
+
6
+ def self.exit_on_failure?() true end
7
+
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ desc "new", "Create a new skiff site [SITE_NAME]"
11
+ def new(site_name)
12
+ self.destination_root = File.expand_path(site_name)
13
+
14
+ @site_name = site_name
15
+ @user_name = `whoami`.strip
16
+
17
+ eval File.read(File.join(File.dirname(__FILE__), "templates/site.rb"))
18
+ end
19
+
20
+ desc "dev", "Start development server"
21
+ def dev
22
+ if File.exist?("Dockerfile")
23
+ puts "Starting #{site_name} on http://localhost:8080..."
24
+
25
+ docker "build -t #{site_name} ."
26
+ docker "run -it --rm -p 8080:80 -v ./public:/site/public --name #{site_name} #{site_name} nginx '-g daemon off;'"
27
+ else
28
+ say "No Dockerfile found in current directory", :red
29
+ end
30
+ end
31
+
32
+ desc "deploy", "Deploy the site"
33
+ option :staging, aliases: "-s", type: :boolean, default: false, desc: "On staging server"
34
+ def deploy
35
+ kamal "setup"
36
+ end
37
+
38
+ desc "flush", "Flush etags after includes have changed (by touching all html files)"
39
+ option :staging, aliases: "-s", type: :boolean, default: false, desc: "On staging server"
40
+ def flush
41
+ kamal_exec 'find /site/public -type f -name "*.html" -exec touch {} \;'
42
+ end
43
+
44
+ desc "restart", "Restart the nginx server with latest config/server.conf"
45
+ option :staging, aliases: "-s", type: :boolean, default: false, desc: "On staging server"
46
+ def restart
47
+ kamal_exec "nginx -t && nginx -s reload"
48
+ end
49
+
50
+ desc "refresh", "Force pull latest changes from git"
51
+ option :staging, aliases: "-s", type: :boolean, default: false, desc: "On staging server"
52
+ def refresh
53
+ kamal_exec 'git checkout -f & git pull \$GIT_URL'
54
+ end
55
+
56
+ desc "logs", "Follow logs from server"
57
+ option :staging, aliases: "-s", type: :boolean, default: false, desc: "On staging server"
58
+ def logs
59
+ kamal "app logs -f"
60
+ end
61
+
62
+ desc "version", "Show Skiff version"
63
+ def version
64
+ say Skiff::VERSION
65
+ end
66
+
67
+ private
68
+ def empty_directory_with_keep_file(destination, config = {})
69
+ empty_directory(destination, config)
70
+ keep_file(destination)
71
+ end
72
+
73
+ def keep_file(destination)
74
+ create_file("#{destination}/.keep")
75
+ end
76
+
77
+ def site_name
78
+ @site_name ||= File.basename(Dir.pwd)
79
+ end
80
+
81
+ def docker(command)
82
+ system "docker #{command}"
83
+ end
84
+
85
+ def kamal(command)
86
+ system "kamal #{command} #{options[:staging] ? "-d staging" : ""}".strip
87
+ end
88
+
89
+ def kamal_exec(commands)
90
+ kamal %(app exec --reuse '/bin/bash -c "#{commands}"')
91
+ end
92
+ end
@@ -0,0 +1,17 @@
1
+ FROM nginx:latest
2
+
3
+ # Install git to provide polling updates
4
+ RUN apt-get update -qq && \
5
+ apt-get install --no-install-recommends -y git && \
6
+ rm -rf /var/lib/apt/lists /var/cache/apt/archives
7
+
8
+ # Site lives here
9
+ WORKDIR /site
10
+
11
+ # Copy site
12
+ COPY . .
13
+
14
+ # Configure nginx
15
+ RUN echo 'include /site/config/server.conf;' > /etc/nginx/conf.d/default.conf
16
+
17
+ CMD ["/site/serve"]
@@ -0,0 +1,39 @@
1
+ # <%= @site_name.capitalize %>
2
+
3
+ This site is managed by [Skiff](https://kamal-deploy.org/skiff).
4
+
5
+ ## Local development
6
+
7
+ If you have a Ruby environment available, you can install Skiff globally with:
8
+
9
+ ```sh
10
+ gem install kamal-skiff
11
+ ```
12
+
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
+
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"
17
+ ```
18
+
19
+ Then run `skiff dev` to start the development server.
20
+
21
+ ## Deploying changes to production (or staging)
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.
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.
26
+
27
+ ## Deploying the site for the first time
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).
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).
32
+
33
+ Finally, you must add the server address into `config/deploy.yml`, and ensure that the image and repository configurations are correct.
34
+
35
+ 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
+
37
+ ## Flushing etag caches after changing include files
38
+
39
+ Skiff uses [Server Side Includes](https://nginx.org/en/docs/http/ngx_http_ssi_module.html), which can change independently of your individual HTML files. When that happens, the caching etags for those latter files will not be updated automatically to reflect the change. You can run `skiff flush` to touch all the public HTML files, which will flush the etag cache.
@@ -0,0 +1,8 @@
1
+ # Deploy your site to a staging server with skiff stage
2
+ servers:
3
+ - 192.168.0.2
4
+
5
+ # Set this to the git branch the staging server should be pulling from when using auto-updating with GIT_URL
6
+ # env:
7
+ # clear:
8
+ # GIT_BRANCH: staging
@@ -0,0 +1,33 @@
1
+ # Name of your site. Used to uniquely configure containers.
2
+ service: <%= @site_name %>
3
+
4
+ # Name of the container image.
5
+ image: <%= @user_name %>/<%= @site_name %>
6
+
7
+ # Deploy to these servers.
8
+ servers:
9
+ - 192.168.0.1
10
+
11
+ # Credentials for your image host.
12
+ registry:
13
+ # Specify the registry server, if you're not using Docker Hub
14
+ # server: registry.digitalocean.com / ghcr.io / ...
15
+ username: <%= @user_name %>
16
+
17
+ # Always use an access token rather than real password when possible.
18
+ password:
19
+ - SKIFF_REGISTRY_PASSWORD
20
+
21
+ # Check /up against 80
22
+ healthcheck:
23
+ port: 80
24
+
25
+ # Use GIT_URL from env if you want to auto-update site via git pulls.
26
+ # Remember to run `kamal env push` after making changes!
27
+ # env:
28
+ # secret:
29
+ # - GIT_URL
30
+
31
+ # Use a different ssh user than root
32
+ # ssh:
33
+ # user: app
@@ -0,0 +1,34 @@
1
+ server {
2
+ listen 80;
3
+
4
+ # Configure URL rewrites
5
+ # rewrite ^/old-pricing$ /pricing last;
6
+
7
+ # Only needed if there's no CDN in front
8
+ gzip on;
9
+
10
+ # Turn on SSI with etags
11
+ ssi on;
12
+ ssi_last_modified on;
13
+
14
+ # All web accessible files live here
15
+ root /site/public;
16
+
17
+ # Map error pages
18
+ error_page 404 /_errors/404.html;
19
+
20
+ # Folders starting with _ are not publicly accessible
21
+ location ~ ^/_.*$ {
22
+ internal;
23
+ }
24
+
25
+ # Make /up look for /site/public/up.html
26
+ location ~ ^/([^\.]+)$ {
27
+ try_files /$1.html =404;
28
+ }
29
+
30
+ # Make /pricing/ look for /site/public/pricing/index.html
31
+ location / {
32
+ index index.html;
33
+ }
34
+ }
@@ -0,0 +1,2 @@
1
+ # Ignore env file
2
+ /.env
@@ -0,0 +1,2 @@
1
+ SKIFF_REGISTRY_PASSWORD=YOUR_TOKEN
2
+ GIT_URL=https://YOUR_TOKEN:@github.com/<%= @user_name %>/<%= @site_name %>.git
@@ -0,0 +1,2 @@
1
+ # Ignore env file
2
+ /.env
@@ -0,0 +1,6 @@
1
+ <!--# set var="title" value="404: Not Found" -->
2
+ <!--# include file="/_includes/header.html" -->
3
+
4
+ <h1>404: Not Found!</h1>
5
+
6
+ <!--# include file="/_includes/footer.html" -->
@@ -0,0 +1,2 @@
1
+ </body>
2
+ </html>
@@ -0,0 +1,5 @@
1
+ <html>
2
+ <head>
3
+ <title><!--# echo var="title" --></title>
4
+ </head>
5
+ <body>
@@ -0,0 +1,6 @@
1
+ <!--# set var="title" value="Skiff site" -->
2
+ <!--# include file="/_includes/header.html" -->
3
+
4
+ <h1>O'hoy!</h1>
5
+
6
+ <!--# include file="/_includes/footer.html" -->
@@ -0,0 +1,7 @@
1
+ <html>
2
+ <head>
3
+ <title>Up</title>
4
+ </head>
5
+ <body style="background-color: green;">
6
+ </body>
7
+ </html>
@@ -0,0 +1,16 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ polling_pull() {
5
+ while true; do
6
+ echo "Pulling latest..."
7
+ git pull $GIT_URL $GIT_BRANCH || true
8
+ sleep 10
9
+ done
10
+ }
11
+
12
+ # When GIT_URL is set start polling in the background
13
+ [[ "$GIT_URL" ]] && polling_pull &
14
+
15
+ # Start NGINX in the foreground
16
+ nginx -g 'daemon off;'
@@ -0,0 +1,19 @@
1
+ template "dotfiles/env.tt", ".env"
2
+ copy_file "dotfiles/gitignore", ".gitignore"
3
+ copy_file "dotfiles/dockerignore", ".dockerignore"
4
+
5
+ empty_directory "config"
6
+ template "config/deploy.yml.tt", "config/deploy.yml"
7
+ copy_file "config/deploy.staging.yml", "config/deploy.staging.yml"
8
+ copy_file "config/server.conf", "config/server.conf"
9
+
10
+ directory "public"
11
+ empty_directory_with_keep_file "public/assets/images"
12
+ empty_directory_with_keep_file "public/assets/javascripts"
13
+ empty_directory_with_keep_file "public/assets/stylesheets"
14
+
15
+ copy_file "Dockerfile"
16
+ template "README.md.tt", "README.md"
17
+
18
+ copy_file "serve"
19
+ chmod "serve", 0755, verbose: false
@@ -0,0 +1,3 @@
1
+ module Skiff
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kamal-skiff
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - David Heinemeier Hansson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-10-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: kamal
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: zeitwerk
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.5'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: debug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: mocha
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: railties
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description:
98
+ email: dhh@hey.com
99
+ executables:
100
+ - skiff
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - MIT-LICENSE
105
+ - README.md
106
+ - bin/skiff
107
+ - lib/kamal-skiff.rb
108
+ - lib/skiff/cli.rb
109
+ - lib/skiff/templates/Dockerfile
110
+ - lib/skiff/templates/README.md.tt
111
+ - lib/skiff/templates/config/deploy.staging.yml
112
+ - lib/skiff/templates/config/deploy.yml.tt
113
+ - lib/skiff/templates/config/server.conf
114
+ - lib/skiff/templates/dotfiles/dockerignore
115
+ - lib/skiff/templates/dotfiles/env.tt
116
+ - lib/skiff/templates/dotfiles/gitignore
117
+ - lib/skiff/templates/public/_errors/404.html
118
+ - lib/skiff/templates/public/_includes/footer.html
119
+ - lib/skiff/templates/public/_includes/header.html
120
+ - lib/skiff/templates/public/index.html
121
+ - lib/skiff/templates/public/up.html
122
+ - lib/skiff/templates/serve
123
+ - lib/skiff/templates/site.rb
124
+ - lib/skiff/version.rb
125
+ homepage: https://github.com/basecamp/kamal-skiff
126
+ licenses:
127
+ - MIT
128
+ metadata: {}
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ requirements: []
144
+ rubygems_version: 3.4.20
145
+ signing_key:
146
+ specification_version: 4
147
+ summary: Deploy static sites using nginx + SSI with Kamal.
148
+ test_files: []