summaryrefslogtreecommitdiff
path: root/jails
diff options
context:
space:
mode:
Diffstat (limited to 'jails')
-rw-r--r--jails/datagubbe/nginx.conf.j251
-rw-r--r--jails/datagubbe/tasks.yaml52
-rw-r--r--jails/gubbhub/cgit.nginx.conf.j241
-rw-r--r--jails/gubbhub/cgitrc.j220
-rw-r--r--jails/gubbhub/gubbshell/create-repo59
-rw-r--r--jails/gubbhub/gubbshell/delete-repo33
-rw-r--r--jails/gubbhub/gubbshell/edit-repo16
-rw-r--r--jails/gubbhub/gubbshell/help21
-rw-r--r--jails/gubbhub/gubbshell/list-repos12
-rw-r--r--jails/gubbhub/tasks.yaml163
-rw-r--r--jails/gubbhub/variables.yaml9
11 files changed, 477 insertions, 0 deletions
diff --git a/jails/datagubbe/nginx.conf.j2 b/jails/datagubbe/nginx.conf.j2
new file mode 100644
index 0000000..d772466
--- /dev/null
+++ b/jails/datagubbe/nginx.conf.j2
@@ -0,0 +1,51 @@
+worker_processes 1;
+
+# This default error log path is compiled-in to make sure configuration parsing
+# errors are logged somewhere, especially during unattended boot when stderr
+# isn't normally logged anywhere. This path will be touched on every nginx
+# start regardless of error log location configured here. See
+# https://trac.nginx.org/nginx/ticket/147 for more info.
+#
+#error_log /var/log/nginx/error.log;
+#
+
+#pid logs/nginx.pid;
+
+
+events {
+ worker_connections 1024;
+}
+
+
+http {
+ include mime.types;
+ default_type application/octet-stream;
+
+ #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+ # '$status $body_bytes_sent "$http_referer" '
+ # '"$http_user_agent" "$http_x_forwarded_for"';
+
+ #access_log logs/access.log main;
+
+ sendfile on;
+ #tcp_nopush on;
+
+ #keepalive_timeout 0;
+ keepalive_timeout 65;
+
+ #gzip on;
+
+ server {
+ listen [::]:80;
+ server_name {{ server_name }};
+
+ #charset koi8-r;
+
+ #access_log logs/host.access.log main;
+
+ location / {
+ root {{ root }};
+ index index.html index.htm;
+ }
+ }
+}
diff --git a/jails/datagubbe/tasks.yaml b/jails/datagubbe/tasks.yaml
new file mode 100644
index 0000000..b10889c
--- /dev/null
+++ b/jails/datagubbe/tasks.yaml
@@ -0,0 +1,52 @@
+- name: create webroot
+ jexec:
+ cmd: mkdir -p /var/www/html
+ jail: "{{ jail.name }}"
+
+- name: create index file
+ ansible.builtin.copy:
+ content: |
+ <!DOCTYPE html>
+ <html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Welcome to datagubbe.dev</title>
+ <style type="text/css">
+ body {
+ background-color: #222;
+ color: #ccc;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>Datagubbe</h1>
+ </body>
+ </html>
+ dest: "{{ jailbase }}/{{ jail.name }}/var/www/html/index.html"
+
+- name: install nginx
+ community.general.pkgng:
+ name:
+ - nginx
+ state: latest
+ jail: "{{ jail.name }}"
+
+- name: create nginx config
+ ansible.builtin.template:
+ src: nginx.conf.j2
+ dest: "{{ jailbase }}/{{ jail.name }}/usr/local/etc/nginx/nginx.conf"
+ vars:
+ root: "/var/www/html"
+ server_name: "datagubbe.dev"
+
+- name: enable nginx
+ community.general.sysrc:
+ name: nginx_enable
+ value: "YES"
+ jail: "{{ jail.name }}"
+
+- name: start nginx
+ jexec:
+ cmd: service nginx status || service nginx start
+ jail: "{{ jail.name }}"
+
diff --git a/jails/gubbhub/cgit.nginx.conf.j2 b/jails/gubbhub/cgit.nginx.conf.j2
new file mode 100644
index 0000000..3593e5b
--- /dev/null
+++ b/jails/gubbhub/cgit.nginx.conf.j2
@@ -0,0 +1,41 @@
+worker_processes 1;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ include mime.types;
+ default_type application/octet-stream;
+ sendfile on;
+ keepalive_timeout 65;
+ gzip on;
+
+ # Cgit
+ server {
+ listen [::]:80;
+ server_name git.datagubbe.dev;
+ root /usr/local/www/cgit;
+ try_files $uri @cgit;
+
+ # Configure HTTP transport
+ location ~ /.+/(info/refs|git-upload-pack) {
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME /usr/local/libexec/git-core/git-http-backend;
+ fastcgi_param PATH_INFO $uri;
+ fastcgi_param GIT_HTTP_EXPORT_ALL 1;
+ fastcgi_param GIT_PROJECT_ROOT /git/repos;
+ fastcgi_param HOME /git/repos;
+ fastcgi_pass unix:/var/run/fcgiwrap/fcgiwrap.sock;
+ }
+
+ location @cgit {
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root/cgit.cgi;
+ fastcgi_param PATH_INFO $uri;
+ fastcgi_param QUERY_STRING $args;
+ fastcgi_param HTTP_HOST $server_name;
+ fastcgi_pass unix:/var/run/fcgiwrap/fcgiwrap.sock;
+ }
+ }
+}
diff --git a/jails/gubbhub/cgitrc.j2 b/jails/gubbhub/cgitrc.j2
new file mode 100644
index 0000000..ef1f50b
--- /dev/null
+++ b/jails/gubbhub/cgitrc.j2
@@ -0,0 +1,20 @@
+css=/cgit.css
+logo=/cgit.png
+
+root-title=git.datagubbe.dev
+root-desc=Git hosting for datagubbar
+
+# disallow http transport git clone, this is handled with git
+enable-http-clone=0
+clone-url=https://$HTTP_HOST/$CGIT_REPO_URL
+
+# if you do not want that webcrawler (like google) index your site
+robots=noindex, nofollow
+
+# if cgit messes up links, use a virtual-root. For example, cgit.example.org/ has this value:
+virtual-root=/
+
+snapshots=tar.xz tar.gz zip
+
+section-from-path=1
+scan-path=/git/repos/
diff --git a/jails/gubbhub/gubbshell/create-repo b/jails/gubbhub/gubbshell/create-repo
new file mode 100644
index 0000000..07c7aa4
--- /dev/null
+++ b/jails/gubbhub/gubbshell/create-repo
@@ -0,0 +1,59 @@
+#! /usr/bin/env sh
+
+set -euo pipefail
+
+if ! id -nG | grep -qwF "gitadm"; then
+ echo $'\e[31myou are not an admin\e[0m'
+ exit 13
+fi
+
+if [ $# -lt 1 ]; then
+ echo $'\e[31mrepository name is required\e[0m'
+ exit 1
+fi
+
+read_with_default() {
+ local var="$1"
+ local title="$2"
+ local default="$3"
+
+ read -p $'\e[36m'"$title"$'\e[0m \e[1m['"$default"$']\e[0m: ' $var
+ eval vval="\$$var"
+ eval $var="\"${vval:-$default}\""
+}
+
+name="$1"
+path="$(echo "$1" | sed 's/ /-/' | tr '[:upper:]' '[:lower:]').git"
+
+if [ -e "$path" ]; then
+ echo $'\e[31m'"repository at \"$path\" already exists"$'\e[0m'
+ exit 1
+fi
+
+read_with_default defbranch "default branch" "main"
+read_with_default dispname "display name" "$name"
+read_with_default owner "owner" "$(id -un)"
+read_with_default shared "shared with 'gitdev' group" "yes"
+
+echo $'\e[36mdescription\e[0m (terminate with C-d): '
+description=""
+while read -r descline; do
+ description="$description$descline\n"
+done
+
+echo "creating repo at: $path..."
+sharerepo="false"
+case "$(echo "$shared" | tr '[:upper:]' '[:lower:]')" in
+ y|yes|ye|true|t) sharerepo="group" ;;
+esac
+git init --bare --shared="$sharerepo" --initial-branch="$defbranch" "$path"
+
+echo "generating web config..."
+cat <<EOF > "$path/cgitrc"
+name=$dispname
+owner=$owner
+desc=${description%\\n}
+EOF
+
+echo "browse new repo at: https://git.datagubbe.dev/$path"
+
diff --git a/jails/gubbhub/gubbshell/delete-repo b/jails/gubbhub/gubbshell/delete-repo
new file mode 100644
index 0000000..ee8b2c6
--- /dev/null
+++ b/jails/gubbhub/gubbshell/delete-repo
@@ -0,0 +1,33 @@
+#! /usr/bin/env sh
+
+set -euo pipefail
+
+if ! id -nG | grep -qwF "gitadm"; then
+ echo $'\e[31myou are not an admin\e[0m'
+ exit 13
+fi
+
+if [ $# -lt 1 ]; then
+ echo $'\e[31mrepository name is required\e[0m'
+ exit 1
+fi
+
+name="$1"
+path="$(echo "$1" | sed 's/ /-/' | tr '[:upper:]' '[:lower:]').git"
+
+read -p $'\e[33mare you sure you want to delete the repo '"\"$name\" at \"$path\""$'\e[0m \e[1m[no]\e[0m: ' confirm
+
+delete="false"
+case "$(echo "$confirm" | tr '[:upper:]' '[:lower:]')" in
+ y|yes|ye) delete="true" ;;
+esac
+
+if [ "$delete" = "true" ]; then
+ echo -n "deleting repository \"$name\"..."
+ rm -rf "$path"
+ echo "done!"
+fi
+
+# delete the dir if empty
+dir=$(dirname "$path")
+find "$dir" -maxdepth 0 -type d -delete
diff --git a/jails/gubbhub/gubbshell/edit-repo b/jails/gubbhub/gubbshell/edit-repo
new file mode 100644
index 0000000..6ceb6f3
--- /dev/null
+++ b/jails/gubbhub/gubbshell/edit-repo
@@ -0,0 +1,16 @@
+#! /usr/bin/env sh
+set -euo pipefail
+
+if ! id -nG | grep -qwF "gitadm"; then
+ echo $'\e[31myou are not an admin\e[0m'
+ exit 13
+fi
+
+if [ $# -lt 1 ]; then
+ echo $'\e[31mrepository name is required\e[0m'
+ exit 1
+fi
+
+path="$(echo "$1" | sed 's/ /-/' | tr '[:upper:]' '[:lower:]').git"
+
+nano -R "$path/cgitrc"
diff --git a/jails/gubbhub/gubbshell/help b/jails/gubbhub/gubbshell/help
new file mode 100644
index 0000000..5ea3e62
--- /dev/null
+++ b/jails/gubbhub/gubbshell/help
@@ -0,0 +1,21 @@
+#! /usr/bin/env sh
+
+printf "Hi $(id -un) and welcome to the gubbshell 👴🐚!
+
+If you have administrative rights this shell can be used to manage repos.
+
+Commands:
+ - \033[1mcreate-repo\033[0m NAME
+ create a new repository called NAME. The command will
+ prompt for needed information. To create a repo in a group use <group>/name.
+
+ - \033[1mdelete-repo\033[0m NAME
+ delete the repository NAME. Note that this is an irreversible operation.
+
+ - \033[1mlist-repos\033[0m
+ list current repos
+
+ - \033[1medit-repo\033[0m NAME
+ edit repository information for NAME. This will open a restricted editor (nano)
+ for editing the repo-specific cgitrc file.
+"
diff --git a/jails/gubbhub/gubbshell/list-repos b/jails/gubbhub/gubbshell/list-repos
new file mode 100644
index 0000000..a33a84b
--- /dev/null
+++ b/jails/gubbhub/gubbshell/list-repos
@@ -0,0 +1,12 @@
+#! /usr/bin/env sh
+
+set -euo pipefail
+
+printf '%-32s %-32s %s\n' 'DISPLAY NAME' 'OWNER' 'PATH'
+echo '-------------------------------------------------------------------------------------------'
+cd /git/repos && find . -name '*.git' -type d |
+while read repo; do
+ name="$(grep "name=" "$repo/cgitrc" | sed 's/^.*=//')"
+ owner="$(grep "owner=" "$repo/cgitrc" | sed 's/^.*=//')"
+ printf '%-32s %-32s %s\n' "$name" "$owner" "$repo"
+done
diff --git a/jails/gubbhub/tasks.yaml b/jails/gubbhub/tasks.yaml
new file mode 100644
index 0000000..4f8c2f2
--- /dev/null
+++ b/jails/gubbhub/tasks.yaml
@@ -0,0 +1,163 @@
+- name: load task vars
+ ansible.builtin.include_vars: ./variables.yaml
+
+- name: install git and cgit
+ community.general.pkgng:
+ name:
+ - git
+ - cgit
+ jail: "{{ jail.name }}"
+
+- name: install nginx and fcgiwrap
+ community.general.pkgng:
+ name:
+ - nginx
+ - fcgiwrap
+ jail: "{{ jail.name }}"
+
+- name: enable fcgiwrap
+ community.general.sysrc:
+ name: fcgiwrap_enable
+ value: "YES"
+ jail: "{{ jail.name }}"
+
+- name: set nginx permissions on fcgiwrap
+ community.general.sysrc:
+ name: fcgiwrap_socket_group
+ value: "www"
+ jail: "{{ jail.name }}"
+
+- name: start fcgiwrap
+ jexec:
+ cmd: service fcgiwrap restart
+ jail: "{{ jail.name }}"
+
+- name: enable nginx
+ community.general.sysrc:
+ name: nginx_enable
+ value: "YES"
+ jail: "{{ jail.name }}"
+
+- name: create groups
+ jexec:
+ cmd: |
+ getent group gitdev || pw groupadd gitdev
+ getent group gitadm || pw groupadd gitadm
+ jail: "{{ jail.name }}"
+
+- name: mount and set up git in zfs
+ jexec:
+ cmd: |
+ [ $(zfs get -H -o value mountpoint {{ gitdataset }}) == "/git" ] && \
+ [ $(zfs get -H -o value mounted {{ gitdataset }}) == "yes" ] || \
+ zfs set mountpoint=/git {{ gitdataset }}
+ jail: "{{ jail.name }}"
+
+- name: enable zfs compression on git data
+ jexec:
+ cmd: |
+ zfs set compression=on {{ gitdataset }}
+ jail: "{{ jail.name }}"
+
+- name: create folders and set permissions
+ jexec:
+ cmd: |
+ mkdir -p /git/repos
+ chown root:gitdev /git/repos
+ chmod g+rws /git/repos
+ mkdir -p /git/sshkeys
+ jail: "{{ jail.name }}"
+
+- name: enable sshd
+ community.general.sysrc:
+ name: sshd_enable
+ value: "YES"
+ jail: "{{ jail.name }}"
+
+- name: create git shell command dir
+ ansible.builtin.file:
+ path: "{{ jailroot }}/git/repos/git-shell-commands"
+ state: directory
+
+- name: setup gubbshell
+ ansible.builtin.copy:
+ src: ./gubbshell/
+ dest: "{{ jailroot }}/git/repos/git-shell-commands/"
+ mode: "g=rx"
+
+- name: install nano
+ community.general.pkgng:
+ name:
+ - nano
+ jail: "{{ jail.name }}"
+
+- name: set correct permissions for gubbshell scripts
+ jexec:
+ cmd: chgrp gitadm /git/repos/git-shell-commands/create-repo /git/repos/git-shell-commands/delete-repo /git/repos/git-shell-commands/edit-repo
+ jail: "{{ jail.name }}"
+
+- name: disable motd
+ jexec:
+ cmd: touch /git/repos/.hushlogin
+ jail: "{{ jail.name }}"
+
+- name: create users
+ jexec:
+ cmd: |
+ pw useradd {{ item.key }} -g gitdev -s /usr/local/libexec/git-core/git-shell -d /git/repos
+ {% if item.value.admin %}
+ pw usermod {{ item.key }} -G gitadm
+ {% endif %}
+ jail: "{{ jail.name }}"
+ loop: "{{ users | dict2items }}"
+ loop_control:
+ label: "{{ item.key }}"
+
+- name: upload pubkeys
+ ansible.builtin.copy:
+ content: "{{ item.value.ssh_keys | join('\n') }}"
+ dest: "{{ jailroot }}/git/sshkeys/{{ item.key }}"
+ owner: "{{ item.key }}"
+ mode: 0400
+ when: item.value.ssh_keys is defined
+ loop: "{{ users | dict2items }}"
+ loop_control:
+ label: "{{ item.key }}"
+
+- name: configure sshd
+ ansible.builtin.lineinfile:
+ path: "{{ jailroot }}/etc/ssh/sshd_config"
+ regex: "^(#)?{{item.key}}"
+ line: "{{item.key}} {{item.value}}"
+ state: present
+ loop:
+ - { key: "PermitRootLogin", value: "no" }
+ - { key: "PasswordAuthentication", value: "no" }
+ - { key: "ChallengeResponseAuthentication", value: "no" }
+ - { key: "UsePAM", value: "no" }
+ - { key: "AuthorizedKeysFile", value: "/git/sshkeys/%u" }
+ register: sshd_conf
+
+- name: configure nginx for cgit
+ ansible.builtin.template:
+ src: cgit.nginx.conf.j2
+ dest: "{{ jailroot }}/usr/local/etc/nginx/nginx.conf"
+ register: nginx_conf
+
+- name: cgit conf
+ ansible.builtin.template:
+ src: cgitrc.j2
+ dest: "{{ jailroot }}/usr/local/etc/cgitrc"
+ register: cgit_conf
+
+- name: restart nginx
+ when: nginx_conf.changed
+ jexec:
+ cmd: service nginx restart
+ jail: "{{ jail.name }}"
+
+- name: restart sshd
+ when: sshd_conf.changed
+ jexec:
+ cmd: service sshd restart
+ jail: "{{ jail.name }}"
diff --git a/jails/gubbhub/variables.yaml b/jails/gubbhub/variables.yaml
new file mode 100644
index 0000000..20c4bbb
--- /dev/null
+++ b/jails/gubbhub/variables.yaml
@@ -0,0 +1,9 @@
+jailroot: "{{ jailbase }}/{{ jail.name }}"
+gitdataset: "{{ jailset }}/tank/gitdata"
+users:
+ abbe:
+ admin: true
+ ssh_keys:
+ - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDBNLyPSAklU0Uz4BarqyUTvkQN9UiIC+dEO7f+lZ1F0K7/S4aEl3lUy8bE5jOiZaOGJNlsJe0zKEAZ3rhjFE70XoWEY5tojaCn9EycKAclbIH+Tvc6ssirfjhjWYIdLsARMndKzcKszNfI7+bYq76miJyzkb8umzxNvecqF9AMK0ZvZaaLwmgIOUy7cSn4ZvU/8U6aBuPsSsOx3i7F1nm0hcy3TCI4OOUN454Ajqub4529Q68iqIZZ9GhppbogCuHuJEMI1OJMPiSUklgtOq4fPnzM6J4uIBsnQ1deSgw+T0QsRWQcME/zKEw6MhOcwVO0z+n08irZehgNtxDxjBDy5L3THLbztG3V+zND+DpfyNsHIYlKYDzE4XW74v+fjU4V3lBuR9rFm5KTRAU/Vok7/I6H1WrvXyvbOq/YvqEzW8JCsq53LIk04obR57iG371wdLoSi8RCEaLzPuDlzRK10KzjlVEfpRHgWyaHFbxtuaqkU6BGQqGeOEiLS639Bm2XYVbybezQBNZ2ht1gDTDMVxVsgsmT18eJiS5SEy49chTC5Jpv9qIlb6cSDUUiTABs8S4iN91dLvSWqu3fWzHJqTc14dujTJ9M+BdF2bwlNPSnsH98iXBLJVGgg/jICSi1LBMSymTzCkf/AMhS7YS2ZI1Ma2AxoysXsjpfDYNyRw== cardno:10 138 182
+ sakarias:
+ admin: true