diff --git a/.woodpecker.yml b/.woodpecker.yml index ceb5737..b3f3ca2 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -2,13 +2,18 @@ pipeline: publish: image: plugins/docker registry: registry.nulo.in - repo: registry.nulo.in/sutty/CHANGEME + repo: registry.nulo.in/sutty/geminabox tags: - - ${ALPINE_VERSION} + - ${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH} - latest build_args: + - RUBY_VERSION=${RUBY_VERSION} + - RUBY_PATCH=${RUBY_PATCH} + - NIO4R_VERSION=${NIO4R_VERSION} + - PUMA_VERSION=${PUMA_VERSION} + - HIREDIS_VERSION=${HIREDIS_VERSION} - ALPINE_VERSION=${ALPINE_VERSION} - - BASE_IMAGE=registry.nulo.in/sutty/monit + - BASE_IMAGE=registry.nulo.in/sutty/ruby username: sutty secrets: - docker_password @@ -16,7 +21,19 @@ pipeline: branch: antifascista event: push matrix: - ALPINE_VERSION: - - 3.13.7 - - 3.14.3 - - 3.15.0 + NIO4R_VERSION: 2.5.8 + PUMA_VERSION: 5.6.2 + HIREDIS_VERSION: 0.6.3 + include: + - ALPINE_VERSION: 3.13.6 + RUBY_VERSION: 2.7 + RUBY_PATCH: 5 + - ALPINE_VERSION: 3.13.7 + RUBY_VERSION: 2.7 + RUBY_PATCH: 5 + - ALPINE_VERSION: 3.14.3 + RUBY_VERSION: 2.7 + RUBY_PATCH: 5 + - ALPINE_VERSION: 3.15.0 + RUBY_VERSION: 3.0 + RUBY_PATCH: 3 diff --git a/3.13.6/hiredis-0.6.3-x86_64-linux-musl.gem b/3.13.6/hiredis-0.6.3-x86_64-linux-musl.gem new file mode 100644 index 0000000..c7fb9c0 Binary files /dev/null and b/3.13.6/hiredis-0.6.3-x86_64-linux-musl.gem differ diff --git a/3.13.6/nio4r-2.5.8-x86_64-linux-musl.gem b/3.13.6/nio4r-2.5.8-x86_64-linux-musl.gem new file mode 100644 index 0000000..a6834a6 Binary files /dev/null and b/3.13.6/nio4r-2.5.8-x86_64-linux-musl.gem differ diff --git a/3.13.6/puma-5.6.2-x86_64-linux-musl.gem b/3.13.6/puma-5.6.2-x86_64-linux-musl.gem new file mode 100644 index 0000000..d3fbe0c Binary files /dev/null and b/3.13.6/puma-5.6.2-x86_64-linux-musl.gem differ diff --git a/Dockerfile b/Dockerfile index d93a8d9..190354d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,43 @@ ARG ALPINE_VERSION=3.13.6 -ARG BASE_IMAGE=sutty/monit -FROM ${BASE_IMAGE}:${ALPINE_VERSION} +ARG RUBY_VERSION=2.7 +ARG RUBY_PATCH=5 +ARG BASE_IMAGE=registry.nulo.in/sutty/ruby +FROM ${BASE_IMAGE}:${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH} + +ARG ALPINE_VERSION +ARG NIO4R_VERSION=2.5.8 +ARG PUMA_VERSION=5.6.2 +ARG HIREDIS_VERSION=0.6.3 + MAINTAINER "f " + +ENV RACK_ENV=production +ENV REDIS_SERVER=redis://redis:6379/2 + +RUN getent group 82 || addgroup -g 82 -S www-data +RUN adduser -s /bin/sh -G www-data -h /srv -D ruby +RUN install -dm 2750 -o ruby -g www-data /srv/gems + +RUN apk add --no-cache daemonize + +USER ruby +WORKDIR /srv +COPY --chown=ruby:www-data ./Gemfile . +COPY --chown=ruby:www-data ./config.ru . +COPY --chown=ruby:www-data ./${ALPINE_VERSION}/nio4r-${NIO4R_VERSION}-x86_64-linux-musl.gem . +COPY --chown=ruby:www-data ./${ALPINE_VERSION}/puma-${PUMA_VERSION}-x86_64-linux-musl.gem . +COPY --chown=ruby:www-data ./${ALPINE_VERSION}/hiredis-${HIREDIS_VERSION}-x86_64-linux-musl.gem . + +# Bootstrap +RUN gem install --no-document --user-install \ + ./nio4r-${NIO4R_VERSION}-x86_64-linux-musl.gem \ + ./puma-${PUMA_VERSION}-x86_64-linux-musl.gem \ + ./hiredis-${HIREDIS_VERSION}-x86_64-linux-musl.gem +RUN bundle install --no-cache --clean --path ~/.gem + +COPY ./monit.conf /etc/monit.d/geminabox.conf +COPY ./geminabox.sh /usr/local/bin/geminabox + +USER root +EXPOSE 9292 +VOLUME /srv/gems diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..5236acc --- /dev/null +++ b/Gemfile @@ -0,0 +1,7 @@ +source 'https://rubygems.org' + +gem 'redis-rack' +gem 'hiredis' +gem 'redis', require: %w[redis redis/connection/hiredis] +gem 'geminabox' +gem 'puma' diff --git a/config.ru b/config.ru new file mode 100644 index 0000000..6b78c9f --- /dev/null +++ b/config.ru @@ -0,0 +1,45 @@ +require 'geminabox' +require 'rack/session/redis' +require 'securerandom' + +Geminabox.data = '/srv/gems' +Geminabox.rubygems_proxy = true +Geminabox.allow_remote_failure = true + +# https://github.com/geminabox/geminabox/wiki/Http-Basic-Auth +Geminabox::Server.helpers do + def protected! + unless authorized? + response['WWW-Authenticate'] = %(Basic realm="Geminabox") + halt 401, "No pushing or deleting without auth.\n" + end + end + + def authorized? + @auth ||= Rack::Auth::Basic::Request.new(request.env) + @auth.provided? && + @auth.basic? && + @auth.credentials && + @auth.credentials == [ENV.fetch('HTTP_BASIC_USER', SecureRandom.hex), + ENV.fetch('HTTP_BASIC_PASSWORD', SecureRandom.hex)] + end +end + +Geminabox::Server.before '/upload' do + protected! +end + +Geminabox::Server.before do + protected! if request.delete? +end + +Geminabox::Server.before '/api/v1/gems' do + unless ENV['HTTP_AUTHORIZATION'] == 'API_KEY' + halt 401, "Access Denied. Api_key invalid or missing.\n" + end +end + +use Rack::Session::Redis, redis_server: ENV['REDIS_SERVER'] +use Rack::Protection + +run Geminabox::Server diff --git a/geminabox.sh b/geminabox.sh new file mode 100755 index 0000000..0893730 --- /dev/null +++ b/geminabox.sh @@ -0,0 +1,24 @@ +#!/bin/sh +set -e + +dir=/srv/gems +pid=/tmp/geminabox.pid + +cd ${dir} + +for link in Gemfile Gemfile.lock .bundle config.ru; do + test -e ${link} || ln -s ../${link} . +done + +chown -R ruby:www-data ${dir} + +case $1 in + start) + rm -f ${pid} + daemonize -p ${pid} -l ${pid} -c ${dir} -u ruby /usr/bin/bundle exec rackup + ;; + start) + test ! -f ${pid} || cat ${pid} | xargs -r kill + rm -f ${pid} + ;; +esac diff --git a/monit.conf b/monit.conf new file mode 100644 index 0000000..b35e24f --- /dev/null +++ b/monit.conf @@ -0,0 +1,4 @@ +check process geminabox with pidfile /tmp/geminabox.pid + start program = "/usr/local/bin/geminabox start" + stop program = "/usr/local/bin/geminabox stop" + if failed port 9292 protocol http for 3 times within 5 cycles then restart