From fb2eef675a5d0ba08039fa1cdd4eb46254f8d5e6 Mon Sep 17 00:00:00 2001 From: Magic_RB Date: Thu, 14 Jan 2021 00:40:58 +0100 Subject: [PATCH] Gitea and PostgreSQL: huge update! --- docker/bash-lib/main.bash | 20 +++ docker/gitea/default.nix | 62 +++------ docker/gitea/init | 82 ++++++++++++ docker/postgresql/default.nix | 214 +++---------------------------- docker/postgresql/init | 235 ++++++++++++++++++++++++++++++++++ 5 files changed, 374 insertions(+), 239 deletions(-) create mode 100644 docker/bash-lib/main.bash create mode 100644 docker/gitea/init create mode 100644 docker/postgresql/init diff --git a/docker/bash-lib/main.bash b/docker/bash-lib/main.bash new file mode 100644 index 0000000..4288789 --- /dev/null +++ b/docker/bash-lib/main.bash @@ -0,0 +1,20 @@ +set -u +e + +## Args +# - vars - a space separated list of variables +save_env() { + local vars="$1" + + for var in $vars ; do + echo "$var=${!var}" + done +} + +## Args +# - message - message to exit with +echo_exit() { + local msg="$1 Exiting..." + + echo $msg + exit 1 +} diff --git a/docker/gitea/default.nix b/docker/gitea/default.nix index a90c336..99a59c7 100644 --- a/docker/gitea/default.nix +++ b/docker/gitea/default.nix @@ -1,10 +1,10 @@ { pkgs, system, nixpkgs, ... }: let # pkgs = (import nixpkgs { inherit system; }).pkgsMusl; - init = let + env = let defaults = { - uid = builtins.toString 5001; - gid = builtins.toString 5001; + userUid = builtins.toString 5001; + userGid = builtins.toString 5001; user = "gitea"; data = "/data/gitea"; }; @@ -27,51 +27,31 @@ let sendEmailSupport = false; }; }; + bashLib = ../bash-lib; in - with pkgs; with defaults; pkgs.writeShellScriptBin "init" '' - if [[ $(${busybox}/bin/id -u) = 0 ]] ; then - -${busybox}/bin/cat << EOF -### Gitea Nix Image Manual -## -## USER_UID ? ${uid} - default user id -## USER_GID ? ${gid} - default group id -## for other options please look at https://docs.gitea.io/en-us/install-with-docker/#environment-variables - -### Recommended volumes (many directories which exist in normal Docker containers, do not exist in this one) -## -## - ${data} - Gitea base data folder -EOF - - export _user_uid="''${USER_UID:-${uid}}" \ - _user_uid="''${USER_UID:-${uid}}" \ - _user="''${USER:-${user}}" - -${busybox}/bin/cat << EOF -### Starting with options: -## USER_UID = "$_user_uid" -## USER_GID = "$_user_uid" -EOF - - - echo "gitea:x:$_uid:$_postgres_gid:Gitea:${data}:${bash}/bin/bash" > /etc/passwd - echo "gitea:x:$_gid:" > /etc/group - - ${busybox}/bin/mkdir -p ${data} - - exec ${busybox}/bin/su -p gitea -c "$0" - else + with pkgs; with defaults; pkgs.writeShellScriptBin "conf" '' + _conf_user_uid=${userUid} + _conf_user_gid=${userGid} + _conf_user=${user} + _conf_data=${data} - exec ${custom.gitea}/bin/gitea $@ - - fi - ''; + _prog_busybox=${busybox} + _prog_gitea=${custom.gitea} + _prog_bash=${bash} + _prog_bash_lib=${bashLib} + ''; + csiMount = pkgs.runCommandNoCC + "csiMount" {} + ''${pkgs.busybox}/bin/mkdir -p $out/data/gitea''; + init = pkgs.writeShellScript "init" (builtins.readFile ./init); in pkgs.dockerTools.buildLayeredImage { name = "gitea"; tag = "latest"; + contents = csiMount; + config = { - Cmd = [ "${init}/bin/init" ]; + Entrypoint = [ "${init}" "${env}/bin/conf"]; }; } diff --git a/docker/gitea/init b/docker/gitea/init new file mode 100644 index 0000000..38382b9 --- /dev/null +++ b/docker/gitea/init @@ -0,0 +1,82 @@ +# -*- mode: shell-script; -*- + +conf=$1 +source $conf + +source $_prog_bash_lib/main.bash + +if [[ $($_prog_busybox/bin/id -u) = 0 ]] ; then + $_prog_busybox/bin/cat << EOF +### Gitea Nix Image Manual +## +## USER_UID ? $_conf_user_uid - default user id +## USER_GID ? $_conf_user_gid - default group id +## APP_INI - app.ini file location for Gitea, will not overwrite existing config! +## for other options please look at https://docs.gitea.io/en-us/install-with-docker/#environment-variables + +### Recommended volumes (many directories which exist in normal Docker containers, do not exist in this one) +## +## - $_conf_data - Gitea base data folder + +EOF + + _user_uid="${USER_UID:-$_conf_user_uid}" + _user_gid="${USER_GID:-$_conf_user_gid}" + _app_ini="${APP_INIT:-}" + + $_prog_busybox/bin/cat << EOF +### Starting with options: +## USER_UID = "$_user_uid" +## USER_GID = "$_user_gid" +EOF + + ( + set -e + echo "gitea:x:$_user_uid:$_user_gid:Gitea:$_conf_data:$_prog_bash/bin/bash" > /etc/passwd + echo "gitea:x:$_user_gid:" > /etc/group + ) || echo_exit "Failed to create user and group!" + + $_prog_busybox/bin/mkdir -p $_conf_data /tmp + + data_uid=$($_prog_busybox/bin/stat -c '%u' $_conf_data || \ + echo_exit "Failed to get uid of $_conf_data") + data_gid=$($_prog_busybox/bin/stat -c '%g' $_conf_data || \ + echo_exit "Failed to get gid of $_conf_data") + if [[ $data_uid != $_user_uid ]] || [[ $data_gid != $_user_gid ]] ; then + $_prog_busybox/bin/chown gitea:gitea $_conf_data /tmp || \ + echo_exit "Failed to chown $_conf_data! (uid: $data_uid, gid: $data_gid)" + fi + + if [[ ! -z "$_app_ini" ]] ; then + if [[ -f "$_app_ini" ]] ; then + if [[ ! -f "$_conf_data/app.ini" ]] ; then + cp "$_app_ini" "$_conf_data/app.ini" + else + echo_exit "APP_INI set, but $_conf_data/app.ini exists!" + fi + else + echo_exit "APP_INI set, but $_app_ini does not exist!" + fi + fi + + + save_env "_user_uid \ + _user_gid \ + _conf_data \ + _prog_gitea" > /env # TODO: exited even though it must have succeded || \ + # echo_exit "Failed to save environment!" + + [[ "$_user_uid" = "0" ]] \ + && echo_exit "UID is set to $_user_uid, which would cause an infinite loop!" + exec $_prog_busybox/bin/su gitea -c "$0 $@" || \ + echo_exit "Failed to switch user!" +else + source /env || \ + echo_exit "Failed to source env!" + + export GITEA_WORK_DIR=$_conf_data + + echo + echo "Starting Gitea!" + exec $_prog_gitea/bin/gitea -c $_conf_data/app.ini $@ +fi diff --git a/docker/postgresql/default.nix b/docker/postgresql/default.nix index d12bf10..9437868 100644 --- a/docker/postgresql/default.nix +++ b/docker/postgresql/default.nix @@ -1,6 +1,6 @@ { pkgs, nixpkgs, ... }: let - init = let + env = let defaults = { user = "postgres"; db = "postgres"; @@ -11,211 +11,29 @@ let gid = builtins.toString 5000; }; postgres = pkgs.postgresql_12; + bashLib = ../bash-lib; in - with pkgs; with defaults; pkgs.writeShellScriptBin "init" '' - if [[ $(${busybox}/bin/id -u) = 0 ]] ; then -${busybox}/bin/cat << EOF -### PostgreSQL Nix Image MANUAL -## -## POSTGRES_UID ? ${uid} - default user id -## POSTGRES_GID ? ${gid} - default group id -## POSTGRES_USER ? ${user} - default user -## POSTGRES_PASSWORD - password for POSTGRES_USER -## POSTGRES_DB ? ${db} - default database -## [ NO_CREATE_DB ] - disables the creation of a default user + db # Currently UNUSED !! -## POSTGRES_INITDB_ARGS ? "" - passed to \`initdb\` -## [ POSTGRES_INITDB_WALDIR ] ? ${waldir} - write-ahead log directory -## POSTGRES_HOST_AUTH_METHOD ? ${host_auth_method} - password authentication method -## [ PG_HBA ] - overrides the creation of pg_hba.conf -## PGDATA ? ${data} - PostgreSQL data folder + with pkgs; with defaults; pkgs.writeShellScriptBin "conf" '' + _conf_user=${user}; + _conf_database=${db}; + _conf_host_auth_method=${host_auth_method} + _conf_data=${data} + _conf_waldir=${waldir} + _conf_user_uid=${uid} + _conf_user_gid=${gid} -### Recommended volumes (many directories which exist in normal Docker containers, do not exist in this one) -## -## - ${data} - PostgreSQL data folder -## - ${waldir} - PostgreSQL waldir - -EOF - - export _postgres_user="''${POSTGRES_USER:-${user}}" \ - _postgres_uid="''${POSTGRES_UID:-${uid}}" \ - _postgres_gid="''${POSTGRES_GID:-${gid}}" - - if [[ ! -z "$POSTGRES_PASSWORD" ]] ; then - export _postgres_password="$POSTGRES_PASSWORD" - else - echo 'You must specify the `POSTGRES_PASSWORD` parameter!' ; exit 1 - fi - - export _postgres_db="''${POSTGRES_DB:-${db}}" \ - _no_create_db="''${NO_CREATE_DB:-}" \ - _postgres_initdb_args="''${POSTGRES_INITDB_ARGS:-}" - - if [[ ! -z "''${POSTGRES_INITDB_WALDIR+x}" ]] ; then - export _postgres_initdb_waldir="''${POSTGRES_INITDB_WALDIR:-${waldir}}" - else - export _postgres_initdb_waldir="" - fi - - export _postgres_host_auth_method="''${POSTGRES_HOST_AUTH_METHOD:-${host_auth_method}}" - if [[ ! -z "''${PG_HBA+x}" ]] ; then - if [[ ! -z "$PG_HBA" ]] ; then - if [[ -f "$PG_HBA" ]] ; then - export _pg_hba="$PG_HBA" - else - echo "FILE \"$PG_HBA\" specified in \`PG_HBA'\ does not exist!" ; exit 1 - fi - else - echo 'Parameter `PG_HBA` is set, but empty!' ; exit 1 - fi - else - _ph_hba="" - fi - - export _pgdata="''${PGDATA:-${data}}" - -${busybox}/bin/cat << EOF -## Starting with options: -## POSTGRES_UID = "$_postgres_uid" -## POSTGRES_GID = "$_postgres_gid" -## POSTGRES_USER = "$_postgres_user" -## POSTGRES_PASSWORD = -## POSTGRES_DB = "$_postgres_db" -## NO_CREATE_DB = "$([[ ! -z "$_no_create_db" ]] && echo true || echo false)" -## POSTGRES_INITDB_ARGS = "$_postgres_initdb_args" -## POSTGRES_INITDB_WALDIR = "$([[ ! -z "$_postgres_initdb_waldir" ]] && echo $_postgres_initdb_waldir || echo null)" -## POSTGRES_HOST_AUTH_METHOD = "$_postgres_host_auth_method" -## PG_HBA = "$([[ ! -z "$_pg_hba" ]] && echo $_ph_hba || echo null)" -## PGDATA="$_pgdata" -EOF - - echo "postgres:x:$_postgres_uid:$_postgres_gid:PostgreSQL:$_pgdata:${bash}/bin/bash" > /etc/passwd - echo "postgres:x:$_postgres_gid:" > /etc/group - - if [[ ! -d "$_pgdata" ]] ; then - echo "Creating \`PGDATA\` and chown-ing to \"$_postgres_uid:$_postgres_gid\"" - ${busybox}/bin/mkdir -p "$_pgdata" - ${busybox}/bin/chown postgres:postgres "$_pgdata" - else - _pgdata_uid=$(${busybox}/bin/stat -c "%U" "$_pgdata") - _pgdata_gid=$(${busybox}/bin/stat -c "%G" "$_pgdata") - - if [[ $_pgdata_uid != $_postgres_uid ]] || [[ $_pgdata_gid != $_postgres_gid ]] ; then - echo "\`PGDATA\` already exists but has incorrect owner! \ - ''${_pgdata_uid}:''${_pgdata_gid}" ; echo 1 - fi - fi - - if [[ -s "$_pgdata/PG_VERSION" ]] ; then - _database_exists="true" - else - _database_exists="" - fi - - if [[ ! -z "$_postgres_initdb_waldir" ]] ; then - if [[ ! -d "$_postgres_initdb_waldir" ]] ; then - echo "Creating \`POSTGRES_INITDB_WALDIR\` and chown-ing to \"${uid}:${gid}\"" - ${busybox}/bin/mkdir -p "$_postgres_initdb_waldir" - ${busybox}/bin/chown postgres:postgres "$_postgres_initdb_waldir" - else - _waldir_uid=$(${busybox}/bin/stat -c "%U" "$_postgres_initdb_waldir") - _waldir_gid=$(${busybox}/bin/stat -c "%G" "$_postgres_initdb_waldir") - - if [[ $_waldir_uid != $_postgres_uid ]] || [[ $_waldir_gid != $_postgres_gid ]] ; then - echo "\`POSTGRES_INITDB_WALDIR\` already exists but has incorrect owner! \ - ''${_waldir_uid}:''${_waldir_gid}" ; echo 1 - fi - fi - fi - - ${busybox}/bin/mkdir -p /tmp /bin /run/postgresql - ${busybox}/bin/chown postgres:postgres /tmp /run/postgresql - ${busybox}/bin/ln -s ${busybox}/bin/sh /bin/sh - - exec ${busybox}/bin/su -p postgres -c "$@" - else - ## Next 4 functions are "borrowed" straight from: - ## https://github.com/docker-library/postgres/blob/master/12/docker-entrypoint.sh - ## Thanks! - # start socket-only postgresql server for setting up or running scripts - # all arguments will be passed along as arguments to `postgres` (via pg_ctl) - temp_server_start() { - set -- "$@" -c listen_addresses="" -p "5432" - - PGUSER="$_postgres_user" \ - ${postgres}/bin/pg_ctl -D "$_pgdata" \ - -o "$(printf '%q ' "$@")" \ - -w start - } - - # stop postgresql server after done setting up user and running scripts - temp_server_stop() { - PGUSER="$_postgres_user" \ - ${postgres}/bin/pg_ctl -D "$_pgdata" -m fast -w stop - } - - # Execute sql script, passed via stdin (or -f flag of pqsl) - # usage: docker_process_sql [psql-cli-args] - # ie: docker_process_sql --dbname=mydb <<<'INSERT ...' - # ie: docker_process_sql -f my-file.sql - # ie: docker_process_sql > "$_pgdata/pg_hba.conf" - else - cp "$_pg_hba" "$_pgdata/pg_hba.conf" - fi - - ${postgres}/bin/postgres -D "$_pgdata" - fi + _prog_busybox=${busybox} + _prog_postgres=${postgres} + _prog_bash=${bash} + _prog_bash_lib=${bashLib} ''; + init = pkgs.writeShellScript "init" (builtins.readFile ./init); in pkgs.dockerTools.buildLayeredImage { name = "postgresql"; tag = "latest"; config = { - Cmd = [ "${init}/bin/init" ]; + Cmd = [ "${init}" "${env}/bin/conf" ]; }; } diff --git a/docker/postgresql/init b/docker/postgresql/init new file mode 100644 index 0000000..489807b --- /dev/null +++ b/docker/postgresql/init @@ -0,0 +1,235 @@ +# -*- mode: shell-script; -*- + +conf=$1 +source $conf + +source $_prog_bash_lib/main.bash + +if [[ $(${_prog_busybox}/bin/id -u) = 0 ]] ; then + ${_prog_busybox}/bin/cat << EOF +### PostgreSQL Nix Image MANUAL +## +## USER_UID ? $_conf_user_uid - default user id +## USER_GID ? $_conf_user_gid - default group id +## PASSWORD - password for POSTGRES_USER +## DATABASE ? $_conf_database - default database +## [ NO_CREATE_DB ] - disables the creation of a default user + db # Currently UNUSED !! +## INITDB_ARGS ? "" - passed to \`initdb\` +## [ INITDB_WALDIR ] ? $_conf_waldir - write-ahead log directory +## HOST_AUTH_METHOD ? $_conf_host_auth_method - password authentication method +## [ PG_HBA ] - overrides the creation of pg_hba.conf +## PGDATA ? $_conf_data - PostgreSQL data folder + +### Recommended volumes (many directories which exist in normal Docker containers, do not exist in this one) +## +## - ${_conf_data} - PostgreSQL data folder +## - ${_conf_waldir} - PostgreSQL waldir + +EOF + + _user_uid="${USER_UID:-${_conf_user_uid}}" + _user_gid="${USER_GID:-${_conf_user_gid}}" + + if [[ ! -z "${PASSWORD:-}" ]] ; then + _password="$PASSWORD" + else + echo 'You must specify the `PASSWORD` parameter!' ; exit 1 + fi + + _database="${DATABASE:-${_conf_database}}" + _no_create_db="''${NO_CREATE_DB:-}" + _initdb_args="''${INITDB_ARGS:-}" + + if [[ ! -z "${INITDB_WALDIR+x}" ]] ; then + _initdb_waldir="''${INITDB_WALDIR:-${_conf_waldir}}" + else + _initdb_waldir="" + fi + + _host_auth_method="${HOST_AUTH_METHOD:-${_conf_host_auth_method}}" + if [[ ! -z "${PG_HBA+x}" ]] ; then + if [[ ! -z "${PG_HBA:-}" ]] ; then + if [[ -f "$PG_HBA" ]] ; then + export _pg_hba="$PG_HBA" + else + echo "FILE \"$PG_HBA\" specified in \`PG_HBA'\ does not exist!" ; exit 1 + fi + else + echo 'Parameter `PG_HBA` is set, but empty!' ; exit 1 + fi + else + _pg_hba="" + fi + + export _pgdata="${PGDATA:-${_conf_data}}" + + ${_prog_busybox}/bin/cat << EOF +## Starting with options: +## POSTGRES_UID = "$_user_uid" +## POSTGRES_GID = "$_user_gid" +## POSTGRES_USER = "$_conf_user" +## POSTGRES_PASSWORD = +## POSTGRES_DB = "$_database" +## NO_CREATE_DB = "$([[ ! -z "$_no_create_db" ]] && echo true || echo false)" +## POSTGRES_INITDB_ARGS = "$_initdb_args" +## POSTGRES_INITDB_WALDIR = "$([[ ! -z "$_initdb_waldir" ]] && echo $_initdb_waldir || echo null)" +## POSTGRES_HOST_AUTH_METHOD = "$_host_auth_method" +## PG_HBA = "$([[ ! -z "$_pg_hba" ]] && echo $_pg_hba || echo null)" +## PGDATA="$_pgdata" +EOF + + echo "$_conf_user:x:$_user_uid:$_user_gid:PostgreSQL:$_pgdata:${_prog_bash}/bin/bash" > /etc/passwd + echo "$_conf_user:x:$_user_gid:" > /etc/group + + if [[ ! -d "$_pgdata" ]] ; then + ( + set -e + echo "Creating \`PGDATA\` and chown-ing to \"$_user_uid:$_user_gid\"" + ${_prog_busybox}/bin/mkdir -p "$_pgdata" + ${_prog_busybox}/bin/chown postgres:postgres "$_pgdata" + ) || \ + echo_exit "Failed to create PGDATA!" + else + _pgdata_uid=$(${_prog_busybox}/bin/stat -c "%U" "$_pgdata" || \ + echo_exit "Failed to get uid of PGDATA!") + _pgdata_gid=$(${_prog_busybox}/bin/stat -c "%G" "$_pgdata" || \ + echo_exit "Failed to get gid of PGDATA!") + + if [[ $_pgdata_uid != $_user_uid ]] || [[ $_pgdata_gid != $_user_gid ]] ; then + echo_exit \ + "\`PGDATA\` already exists but has incorrect owner! \ + $_pgdata_uid:$_pgdata_gid" + fi + fi + + if [[ -s "$_pgdata/PG_VERSION" ]] ; then + _database_exists="true" + else + _database_exists="" + fi + + if [[ ! -z "$_initdb_waldir" ]] ; then + if [[ ! -d "$_initdb_waldir" ]] ; then + ( + set -e + echo "Creating \`INITDB_WALDIR\` and chown-ing to \"$_user_uid:$_user_gid\"" + ${busybox}/bin/mkdir -p "$_initdb_waldir" + ${busybox}/bin/chown postgres:postgres "$_postgres_initdb_waldir" + ) || \ + echo_exit "Failed to create INITDB_WALDIR!" + else + _waldir_uid=$(${busybox}/bin/stat -c "%U" "$_postgres_initdb_waldir" || \ + echo_exit "Faile to get uid of INITDB_WALDIR") + _waldir_gid=$(${busybox}/bin/stat -c "%G" "$_postgres_initdb_waldir" || \ + echo_exit "Faile to get gid of INITDB_WALDIR") + + if [[ $_waldir_uid != $_user_uid ]] || [[ $_waldir_gid != $_user_gid ]] ; then + echo_exit \ + "\`INITDB_WALDIR\` already exists but has incorrect owner! \ + $_waldir_uid:$_waldir_gid" + fi + fi + fi + + $_prog_busybox/bin/mkdir -p /tmp /bin /run/postgresql || \ + echo_exit "Failed to create necessary directories!" + $_prog_busybox/bin/chown postgres:postgres /tmp /run/postgresql || \ + echo_exit "Failed to chown directories!" + + ## Required due to popen failing with `Cannot allocate memory` of all things + $_prog_busybox/bin/ln -s ${_prog_busybox}/bin/sh /bin/sh || \ + echo_exit "Failed to symlink /bin/sh!" + + save_env "_conf_user \ + _pgdata \ + _database \ + _password \ + _pg_hba \ + _initdb_waldir \ + _initdb_args \ + _host_auth_method \ + _prog_postgres" > /env + + exec $_prog_busybox/bin/su postgres -c "$0 $@" || \ + echo_exit "Failed to switch user!" +else + source /env || \ + echo_exit "Failed to source env!" + + ## Next 4 functions are "borrowed" straight from: + ## https://github.com/docker-library/postgres/blob/master/12/docker-entrypoint.sh + ## Thanks! + # start socket-only postgresql server for setting up or running scripts + # all arguments will be passed along as arguments to `postgres` (via pg_ctl) + temp_server_start() { + set -- "$@" -c listen_addresses="" -p "5432" + + PGUSER="$_conf_user" \ + $_prog_postgres/bin/pg_ctl -D "$_pgdata" \ + -o "$(printf '%q ' "$@")" \ + -w start + } + + # stop postgresql server after done setting up user and running scripts + temp_server_stop() { + PGUSER="$_conf_user" \ + $_prog_postgres/bin/pg_ctl -D "$_pgdata" -m fast -w stop + } + + # Execute sql script, passed via stdin (or -f flag of pqsl) + # usage: docker_process_sql [psql-cli-args] + # ie: docker_process_sql --dbname=mydb <<<'INSERT ...' + # ie: docker_process_sql -f my-file.sql + # ie: docker_process_sql > "$_pgdata/pg_hba.conf" + else + cp "$_pg_hba" "$_pgdata/pg_hba.conf" + fi + + echo "\nStarting PostgreSQL" + exec $_prog_postgres/bin/postgres -D "$_pgdata" +fi