diff --git a/Dockerfile b/Dockerfile index da9c8d3b..4141a4c9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,6 @@ FROM archlinux:base-devel +ENV PYTHONPATH=/aurweb +ENV AUR_CONFIG=conf/config # Setup some default system stuff. RUN ln -sf /usr/share/zoneinfo/UTC /etc/localtime @@ -16,7 +18,7 @@ RUN pacman -Syu --noconfirm --noprogressbar \ python-pytest-asyncio python-coverage hypercorn python-bcrypt \ python-email-validator openssh python-lxml mariadb mariadb-libs \ python-isort flake8 cgit uwsgi uwsgi-plugin-cgi php php-fpm \ - python-asgiref uvicorn + python-asgiref uvicorn python-pip python-wheel RUN useradd -U -d /aurweb -c 'AUR User' aur @@ -25,6 +27,9 @@ COPY docker /docker WORKDIR /aurweb COPY . . -ENV PYTHONPATH=/aurweb - RUN make -C po all install +RUN pip3 install -t /aurweb/app --upgrade -I . + +# Set permissions on directories and binaries. +RUN bash -c 'find /aurweb/app -type d -exec chmod 755 {} \;' +RUN chmod 755 /aurweb/app/bin/* diff --git a/docker-compose.yml b/docker-compose.yml index 795236c7..6bf36166 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -50,33 +50,77 @@ services: image: aurweb:latest init: true environment: - - AUR_CONFIG=conf/config + - AUR_CONFIG=/aurweb/conf/config entrypoint: /docker/git-entrypoint.sh command: /docker/scripts/run-sshd.sh ports: - - "2222:22" + - "2222:2222" healthcheck: test: "bash /docker/health/sshd.sh" interval: 2s timeout: 30s + depends_on: + mariadb: + condition: service_healthy + links: + - mariadb volumes: - mariadb_run:/var/run/mysqld - mariadb_data:/var/lib/mysql - git_data:/aurweb/aur.git - ./cache:/cache - cgit: + smartgit: + image: aurweb:latest + init: true + environment: + - AUR_CONFIG=/aurweb/conf/config + entrypoint: /docker/smartgit-entrypoint.sh + command: /docker/scripts/run-smartgit.sh + healthcheck: + test: "bash /docker/health/smartgit.sh" + interval: 2s + timeout: 30s + depends_on: + mariadb: + condition: service_healthy + links: + - mariadb + volumes: + - mariadb_run:/var/run/mysqld + - mariadb_data:/var/lib/mysql + - git_data:/aurweb/aur.git + - ./cache:/cache + - smartgit_run:/var/run/smartgit + + cgit-php: image: aurweb:latest init: true environment: - AUR_CONFIG=/aurweb/conf/config entrypoint: /docker/cgit-entrypoint.sh - command: >- - uwsgi --socket 0.0.0.0:3000 - --plugins cgi - --cgi /usr/share/webapps/cgit/cgit.cgi + command: /docker/scripts/run-cgit.sh 3000 "https://localhost:8443/cgit" healthcheck: - test: "bash /docker/health/cgit.sh" + test: "bash /docker/health/cgit.sh 3000" + interval: 2s + timeout: 30s + depends_on: + git: + condition: service_healthy + links: + - git + volumes: + - git_data:/aurweb/aur.git + + cgit-fastapi: + image: aurweb:latest + init: true + environment: + - AUR_CONFIG=/aurweb/conf/config + entrypoint: /docker/cgit-entrypoint.sh + command: /docker/scripts/run-cgit.sh 3000 "https://localhost:8444/cgit" + healthcheck: + test: "bash /docker/health/cgit.sh 3000" interval: 2s timeout: 30s depends_on: @@ -170,14 +214,20 @@ services: interval: 2s timeout: 30s depends_on: - cgit: + cgit-php: + condition: service_healthy + cgit-fastapi: + condition: service_healthy + smartgit: condition: service_healthy fastapi: condition: service_healthy php-fpm: condition: service_healthy links: - - cgit + - cgit-php + - cgit-fastapi + - smartgit - fastapi - php-fpm volumes: @@ -187,6 +237,7 @@ services: - ./web/html:/aurweb/web/html - ./web/template:/aurweb/web/template - ./web/lib:/aurweb/web/lib + - smartgit_run:/var/run/smartgit sharness: image: aurweb:latest @@ -298,3 +349,4 @@ volumes: mariadb_run: {} # Share /var/run/mysqld/mysqld.sock mariadb_data: {} # Share /var/lib/mysql git_data: {} # Share aurweb/aur.git + smartgit_run: {} diff --git a/docker/cgit-entrypoint.sh b/docker/cgit-entrypoint.sh index e05e1b7a..9abc5091 100755 --- a/docker/cgit-entrypoint.sh +++ b/docker/cgit-entrypoint.sh @@ -1,13 +1,12 @@ #!/bin/bash set -eou pipefail -cp -vf conf/cgitrc.proto /etc/cgitrc +mkdir -p /var/cache/cgit -sed -ri 's|clone-prefix=.*|clone-prefix=https://localhost:8443|' /etc/cgitrc +cp -vf conf/cgitrc.proto /etc/cgitrc +sed -ri "s|clone-prefix=.*|clone-prefix=${2}|" /etc/cgitrc sed -ri 's|header=.*|header=/aurweb/web/template/cgit/header.html|' /etc/cgitrc sed -ri 's|footer=.*|footer=/aurweb/web/template/cgit/footer.html|' /etc/cgitrc sed -ri 's|repo\.path=.*|repo.path=/aurweb/aur.git|' /etc/cgitrc -mkdir -p /var/cache/cgit - exec "$@" diff --git a/docker/fastapi-entrypoint.sh b/docker/fastapi-entrypoint.sh index 2f04c29f..11b8ac5a 100755 --- a/docker/fastapi-entrypoint.sh +++ b/docker/fastapi-entrypoint.sh @@ -7,4 +7,7 @@ bash $dir/test-mysql-entrypoint.sh sed -ri "s;^(aur_location) = .+;\1 = https://localhost:8444;" conf/config sed -ri 's/^(name) = .+/\1 = aurweb/' conf/config +sed -ri "s|^(git_clone_uri_anon) = .+|\1 = https://localhost:8444/cgit/aur.git -b %s|" conf/config.defaults +sed -ri "s|^(git_clone_uri_priv) = .+|\1 = ssh://aur@localhost:2222/%s.git|" conf/config.defaults + exec "$@" diff --git a/docker/git-entrypoint.sh b/docker/git-entrypoint.sh index d17ceeaf..e6d3ad97 100755 --- a/docker/git-entrypoint.sh +++ b/docker/git-entrypoint.sh @@ -2,44 +2,91 @@ set -eou pipefail SSHD_CONFIG=/etc/ssh/sshd_config +AUTH_SCRIPT=/aurweb/app/git-auth.sh -GIT_REPO=aur.git -GIT_KEY=/cache/git.key +GIT_REPO=/aurweb/aur.git +GIT_BRANCH=master # 'Master' branch. -# Setup SSH Keys. -ssh-keygen -A +if ! grep -q 'PYTHONPATH' /etc/environment; then + echo "PYTHONPATH='/aurweb:/aurweb/app'" >> /etc/environment +else + sed -ri "s|^(PYTHONPATH)=.*$|\1='/aurweb:/aurweb/app'|" /etc/environment +fi + +if ! grep -q 'AUR_CONFIG' /etc/environment; then + echo "AUR_CONFIG='/aurweb/conf/config'" >> /etc/environment +else + sed -ri "s|^(AUR_CONFIG)=.*$|\1='/aurweb/conf/config'|" /etc/environment +fi + +if ! grep -q '/aurweb/app/bin' /etc/environment; then + echo "PATH='/aurweb/app/bin:\${PATH}'" >> /etc/environment +fi # Add AUR SSH config. cat >> $SSHD_CONFIG << EOF Match User aur PasswordAuthentication no - AuthorizedKeysCommand /usr/local/bin/aurweb-git-auth "%t" "%k" + AuthorizedKeysCommand $AUTH_SCRIPT "%t" "%k" AuthorizedKeysCommandUser aur AcceptEnv AUR_OVERWRITE - SetEnv AUR_CONFIG=/aurweb/config/config EOF +cat >> $AUTH_SCRIPT << EOF +#!/usr/bin/env bash +export PYTHONPATH="$PYTHONPATH" +export AUR_CONFIG="$AUR_CONFIG" +export PATH="/aurweb/app/bin:\${PATH}" + +exec /aurweb/app/bin/aurweb-git-auth "\$@" +EOF +chmod 755 $AUTH_SCRIPT + +DB_NAME="aurweb" +DB_HOST="mariadb" +DB_USER="aur" +DB_PASS="aur" + +# Setup a config for our mysql db. +cp -vf conf/config.dev $AUR_CONFIG +sed -i "s;YOUR_AUR_ROOT;$(pwd);g" $AUR_CONFIG +sed -ri "s/^(name) = .+/\1 = ${DB_NAME}/" $AUR_CONFIG +sed -ri "s/^(host) = .+/\1 = ${DB_HOST}/" $AUR_CONFIG +sed -ri "s/^(user) = .+/\1 = ${DB_USER}/" $AUR_CONFIG +sed -ri "s/^;?(password) = .+/\1 = ${DB_PASS}/" $AUR_CONFIG +sed -i "s|/usr/local/bin|/aurweb/app/bin|g" $AUR_CONFIG + +AUR_CONFIG_DEFAULTS="${AUR_CONFIG}.defaults" + +if [[ "$AUR_CONFIG_DEFAULTS" != "/aurweb/conf/config.defaults" ]]; then + cp -vf conf/config.defaults $AUR_CONFIG_DEFAULTS +fi + +# Set some defaults needed for pathing and ssh uris. +sed -i "s|/usr/local/bin|/aurweb/app/bin|g" $AUR_CONFIG_DEFAULTS +sed -ri "s|^(repo-path) = .+|\1 = /aurweb/aur.git/|" $AUR_CONFIG_DEFAULTS + +ssh_cmdline='ssh ssh://aur@localhost:2222' +sed -ri "s|^(ssh-cmdline) = .+|\1 = $ssh_cmdline|" $AUR_CONFIG_DEFAULTS + +# Setup SSH Keys. +ssh-keygen -A + # Taken from INSTALL. mkdir -pv $GIT_REPO # Initialize git repository. if [ ! -f $GIT_REPO/config ]; then + curdir="$(pwd)" cd $GIT_REPO + git config --global init.defaultBranch $GIT_BRANCH git init --bare git config --local transfer.hideRefs '^refs/' git config --local --add transfer.hideRefs '!refs/' git config --local --add transfer.hideRefs '!HEAD' - ln -sf /usr/local/bin/aurweb-git-update hooks/update - chown -R aur . - cd .. + ln -sf /aurweb/app/bin/aurweb-git-update hooks/update + cd $curdir + chown -R aur:aur $GIT_REPO fi -if [ ! -f $GIT_KEY ]; then - # Create a DSA ssh private/pubkey at /cache/git.key{.pub,}. - ssh-keygen -f $GIT_KEY -t dsa -N '' -C 'AUR Git Key' -fi - -# Users should modify these permissions on their local machines. -chmod 666 ${GIT_KEY}{.pub,} - exec "$@" diff --git a/docker/health/cgit.sh b/docker/health/cgit.sh index add33031..2f0cfeb1 100755 --- a/docker/health/cgit.sh +++ b/docker/health/cgit.sh @@ -1,2 +1,2 @@ #!/bin/bash -exec printf "" >>/dev/tcp/127.0.0.1/3000 +exec printf "" >>/dev/tcp/127.0.0.1/${1} diff --git a/docker/health/smartgit.sh b/docker/health/smartgit.sh new file mode 100755 index 00000000..b4e7ebd4 --- /dev/null +++ b/docker/health/smartgit.sh @@ -0,0 +1,2 @@ +#!/bin/bash +exec pgrep uwsgi diff --git a/docker/health/sshd.sh b/docker/health/sshd.sh index 6befdfb5..d9da9ea1 100755 --- a/docker/health/sshd.sh +++ b/docker/health/sshd.sh @@ -1,2 +1,5 @@ #!/bin/bash -exec printf "" >>/dev/tcp/127.0.0.1/22 +# Opt to just pgrep sshd instead of connecting here. This health +# script is used on a regular interval and it ends up spamming +# the git service's logs with accesses. +exec pgrep sshd diff --git a/docker/nginx-entrypoint.sh b/docker/nginx-entrypoint.sh index 1e442ef7..238cd167 100755 --- a/docker/nginx-entrypoint.sh +++ b/docker/nginx-entrypoint.sh @@ -45,8 +45,16 @@ http { server fastapi:8000; } - upstream cgit { - server cgit:3000; + upstream cgit-php { + server cgit-php:3000; + } + + upstream cgit-fastapi { + server cgit-fastapi:3000; + } + + upstream smartgit { + server unix:/var/run/smartgit/smartgit.sock; } server { @@ -59,12 +67,23 @@ http { root /aurweb/web/html; index index.php; + location ~ "^/([a-z0-9][a-z0-9.+_-]*?)(\.git)?/(git-(receive|upload)-pack|HEAD|info/refs|objects/(info/(http-)?alternates|packs)|[0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\.(pack|idx))$" { + include uwsgi_params; + uwsgi_pass smartgit; + uwsgi_modifier1 9; + uwsgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend; + uwsgi_param PATH_INFO /aur.git/\$3; + uwsgi_param GIT_HTTP_EXPORT_ALL ""; + uwsgi_param GIT_NAMESPACE \$1; + uwsgi_param GIT_PROJECT_ROOT /aurweb; + } + location ~ ^/cgit { include uwsgi_params; rewrite ^/cgit/([^?/]+/[^?]*)?(?:\?(.*))?$ /cgit.cgi?url=\$1&\$2 last; uwsgi_modifier1 9; uwsgi_param CGIT_CONFIG /etc/cgitrc; - uwsgi_pass uwsgi://cgit; + uwsgi_pass uwsgi://cgit-php; } location ~ ^/[^/]+\.php($|/) { @@ -95,12 +114,23 @@ http { try_files \$uri @proxy_to_app; } + location ~ "^/([a-z0-9][a-z0-9.+_-]*?)(\.git)?/(git-(receive|upload)-pack|HEAD|info/refs|objects/(info/(http-)?alternates|packs)|[0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\.(pack|idx))$" { + include uwsgi_params; + uwsgi_pass smartgit; + uwsgi_modifier1 9; + uwsgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend; + uwsgi_param PATH_INFO /aur.git/\$3; + uwsgi_param GIT_HTTP_EXPORT_ALL ""; + uwsgi_param GIT_NAMESPACE \$1; + uwsgi_param GIT_PROJECT_ROOT /aurweb; + } + location ~ ^/cgit { include uwsgi_params; rewrite ^/cgit/([^?/]+/[^?]*)?(?:\?(.*))?$ /cgit.cgi?url=\$1&\$2 last; uwsgi_modifier1 9; uwsgi_param CGIT_CONFIG /etc/cgitrc; - uwsgi_pass uwsgi://cgit; + uwsgi_pass uwsgi://cgit-fastapi; } location @proxy_to_app { diff --git a/docker/php-entrypoint.sh b/docker/php-entrypoint.sh index 19c6d059..4d49ef17 100755 --- a/docker/php-entrypoint.sh +++ b/docker/php-entrypoint.sh @@ -7,6 +7,9 @@ bash $dir/test-mysql-entrypoint.sh sed -ri "s;^(aur_location) = .+;\1 = https://localhost:8443;" conf/config sed -ri 's/^(name) = .+/\1 = aurweb/' conf/config +sed -ri "s|^(git_clone_uri_anon) = .+|\1 = https://localhost:8443/cgit/aur.git -b %s|" conf/config.defaults +sed -ri "s|^(git_clone_uri_priv) = .+|\1 = ssh://aur@localhost:2222/%s.git|" conf/config.defaults + sed -ri 's/^(listen).*/\1 = 0.0.0.0:9000/' /etc/php/php-fpm.d/www.conf sed -ri 's/^;?(clear_env).*/\1 = no/' /etc/php/php-fpm.d/www.conf diff --git a/docker/scripts/run-cgit.sh b/docker/scripts/run-cgit.sh new file mode 100755 index 00000000..67bdc079 --- /dev/null +++ b/docker/scripts/run-cgit.sh @@ -0,0 +1,4 @@ +#!/bin/bash +exec uwsgi --socket 0.0.0.0:${1} \ + --plugins cgi \ + --cgi /usr/share/webapps/cgit/cgit.cgi diff --git a/docker/scripts/run-smartgit.sh b/docker/scripts/run-smartgit.sh new file mode 100755 index 00000000..b6869a6c --- /dev/null +++ b/docker/scripts/run-smartgit.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +exec uwsgi \ + --socket /var/run/smartgit/smartgit.sock \ + --uid root \ + --gid http \ + --chmod-socket=666 \ + --plugins cgi \ + --cgi /usr/lib/git-core/git-http-backend diff --git a/docker/scripts/run-sshd.sh b/docker/scripts/run-sshd.sh index a69af7e2..d488e80d 100755 --- a/docker/scripts/run-sshd.sh +++ b/docker/scripts/run-sshd.sh @@ -1,2 +1,2 @@ #!/bin/bash -exec /usr/sbin/sshd -D +exec /usr/sbin/sshd -e -p 2222 -D diff --git a/docker/smartgit-entrypoint.sh b/docker/smartgit-entrypoint.sh new file mode 100755 index 00000000..daa9edeb --- /dev/null +++ b/docker/smartgit-entrypoint.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -eou pipefail + +exec "$@"