Browse Source

Merge branch 'master' of ssh://git.alemor.org:4323/mar/container

feature/startup-from-labels
Mar Alegre 4 years ago
parent
commit
d1337c7670
  1. 6
      .install/bin/pdm-build
  2. 8
      .install/bin/pdm-launch
  3. 6
      .install/bin/pdm-shell
  4. 6
      debian/Containerfile
  5. 20
      debian/assets/bin/esh
  6. 37
      gitea/Containerfile
  7. 3
      gitea/Systemdfile
  8. 16
      gitea/assets/app.ini.esh.esh
  9. 4
      gitea/assets/bin/db-load
  10. 366
      gitea/assets/bin/esh
  11. 2
      gitea/assets/gitea.service
  12. 32
      gitea/assets/sshd_config
  13. 2
      gitea/docs/Build.md
  14. 4
      mailsrv/assets/bin/mkvirt
  15. 4
      mailsrv/assets/postfix/main.cf.part
  16. 6
      mailsrv/docs/Deploy.md

6
.install/bin/pdm-build

@ -9,9 +9,9 @@ epoch=$(date +%s.%3N)
today=$(date +%Y-%m-%d-T%H%M)
badarg() {
echo -n "$(basename $0): "
echo "$1"
echo "Try '$(basename $0) -h' for more information."
echo -n "$(basename $0): " >&2
echo "$1" >&2
echo "Try '$(basename $0) -h' for more information." >&2
exit 2
}

8
.install/bin/pdm-launch

@ -3,9 +3,9 @@
set -eEuo pipefail
badarg() {
echo -n "$(basename $0): "
echo "$1"
echo "Try '$(basename $0) -h' for more information."
echo -n "$(basename $0): " >&2
echo "$1" >&2
echo "Try '$(basename $0) -h' for more information." >&2
exit 2
}
@ -64,7 +64,7 @@ if [[ $opt_config -eq 1 ]]; then
echo "Getting deploy options from image metadata label '$opt_label' ..."
deployconf=$(podman image inspect -f "{{ .Config.Labels.${opt_label} }}" "$image")
if [[ $deployconf == "<no value>" ]]; then
echo "Error: could not find image metadata label '$opt_label'"
echo "Error: could not find image metadata label '$opt_label'" >&2
exit 1
fi
else

6
.install/bin/pdm-shell

@ -3,9 +3,9 @@
set -eEuo pipefail
badarg() {
echo -n "$(basename $0): "
echo "$1"
echo "Try '$(basename $0) -h' for more information."
echo -n "$(basename $0): " >&2
echo "$1" >&2
echo "Try '$(basename $0) -h' for more information." >&2
exit 2
}

6
debian/Containerfile

@ -34,3 +34,9 @@ COPY assets/bash.bashrc /etc/bash.bashrc
# copy custom scripts
COPY assets/bin/ /usr/local/bin/
# Install templating engine
RUN wget https://raw.githubusercontent.com/jirutka/esh/master/esh && \
chmod +x esh && \
mkdir -p /usr/local/lib/esh && \
mv esh /usr/local/lib/esh

20
debian/assets/bin/esh

@ -0,0 +1,20 @@
#!/bin/bash
esh=/usr/local/lib/esh/esh
if [[ $# -gt 2 ]]; then
$esh "$@"
else
if [[ $# -eq 2 ]]; then
out="$2"
elif [[ $1 == *.esh ]]; then
out="${1%.esh}"
else
out='-'
fi
fi
$esh -o "$out" "$1"
chmod $(stat -c '%a' "$1") "$out"
chown $(stat -c '%U:%G' "$1") "$out"

37
gitea/Containerfile

@ -11,6 +11,7 @@ LABEL config_default="\
-v /srv/vol/gitea/git:/vol/git \
-v /srv/vol/gitea/data:/vol/data \
-v /srv/vol/gitea/log:/vol/log \
-v /srv/vol/gitea/keys:/vol/keys \
"
# Build variables
@ -27,7 +28,10 @@ ENV DBNAME=gitea
###
# install packages we want
RUN apt update -y && apt install -y postgresql postgresql-doc git
RUN apt update -y && apt install -y postgresql postgresql-doc git openssh-server
# create directories for volumes
RUN mkdir -p /vol/git /vol/data /vol/log /vol/keys
# put database variables in /etc/environment so anyone can access them
# also autodetect versions of postgres and gitea and put them in /etc/environment as well
@ -39,7 +43,7 @@ RUN echo "DBUSER=$DBUSER" >> /etc/environment && \
# create gitea user with file owner UID
RUN addgroup --gid $FILESUID gitea && \
adduser gitea --ingroup gitea --uid $FILESUID --disabled-password --gecos "Gitea Server" --shell /usr/sbin/nologin --home /var/lib/gitea
adduser gitea --ingroup gitea --uid $FILESUID --disabled-password --gecos "Gitea Server" --shell /bin/bash --home /var/lib/gitea
# copy our custom scripts
COPY assets/bin/ /usr/local/bin/
@ -49,6 +53,16 @@ RUN mkdir -p /vol/log && \
rm -r /var/log && \
ln -s /vol/log /var/log
###
### SSH Server ###
###
# copy sshd config
COPY assets/sshd_config /etc/ssh/sshd_config
# make link to keys volume
RUN ln -s /vol/keys /etc/ssh/keys
###
### PostgreSQL ###
###
@ -67,21 +81,24 @@ RUN wget https://dl.gitea.io/gitea/${GITEAV:?}/gitea-${GITEAV:?}-linux-amd64 &&
chmod +x /usr/local/bin/gitea
# make directories gitea needs
RUN mkdir -p /var/lib/gitea/custom /var/lib/gitea/data/ /var/log/gitea && \
RUN mkdir -p /var/lib/gitea/data/ /var/log/gitea /etc/gitea && \
chown -R gitea:gitea /var/lib/gitea /var/log/gitea && \
chmod -R 750 /var/lib/gitea /var/log/gitea && \
ln -s /var/log/gitea /var/lib/gitea/log
ln -s /var/log/gitea /var/lib/gitea/log && \
ln -s /vol/data/custom /var/lib/gitea/custom
# copy gitea config template
COPY assets/app.ini.esh /etc/gitea/
# template config file
RUN cd /etc/gitea/ && \
esh app.ini.esh > app.ini && \
rm app.ini.esh && \
chmod -R +r /etc/gitea/
COPY assets/app.ini.esh.esh /etc/gitea/
RUN cd /etc/gitea && \
esh app.ini.esh.esh && \
rm app.ini.esh.esh && \
chmod -R +r /etc/gitea
COPY assets/gitea.service /etc/systemd/system/
# make alias for running admin commands from command line easily
RUN echo "alias gitea='sudo -u gitea gitea --config /etc/gitea/app.ini'" >> /root/.bashrc
###
### Crontab
###

3
gitea/Systemdfile

@ -9,6 +9,5 @@ sleep 5
# make database for gitea
db-make
# enable and start gitea
# enable gitea
systemctl enable gitea
systemctl start gitea

16
gitea/assets/app.ini.esh → gitea/assets/app.ini.esh.esh

@ -1,4 +1,5 @@
APP_NAME = Gitea: Git with a cup of tea
<%% . /vol/data/hostvars -%>
APP_NAME = <%%= $pagename %>
RUN_USER = gitea
RUN_MODE = prod
@ -26,13 +27,14 @@ PATH = /var/lib/gitea/data/gitea.db
ROOT = /vol/git/repos
[server]
DOMAIN = git.alemor.org
ROOT_URL = https://git.alemor.org/
DOMAIN = <%% $domain %>
ROOT_URL = https://<%% $domain %>/
HTTP_PORT = 80
START_SSH_SERVER = true
SSH_PORT = 4323
SSH_LISTEN_PORT = 22
LFS_START_SERVER = trxue
START_SSH_SERVER = false
SSH_PORT = <%% $sshport %%>
SSH_CREATE_AUTHORIZED_KEYS_FILE = true
SSH_AUTHORIZED_KEYS_BACKUP = false
LFS_START_SERVER = true
LFS_CONTENT_PATH = /vol/git/lfs
LFS_JWT_SECRET = <%= $(gitea generate secret JWT_SECRET) %>
OFFLINE_MODE = true

4
gitea/assets/bin/db-load

@ -1,10 +1,10 @@
#!/bin/bash
status=$(systemctl show gitea -p ActiveState --value)
if [[ $status == active]]; then
if [[ $status == active ]]; then
systemctl stop gitea
fi
db-make
psql -U $DBUSER -d $DBNAME -f $1
if [[ $status == active]]; then
if [[ $status == active ]]; then
systemctl start gitea
fi

366
gitea/assets/bin/esh

@ -1,366 +0,0 @@
#!/bin/sh
# vim: set ts=4:
#---help---
# USAGE:
# esh [options] [--] <input> [<variable>...]
# esh <-h | -V>
#
# Process and evaluate an ESH template.
#
# ARGUMENTS:
# <input> Path of the template file or "-" to read from STDIN.
# <variable> Variable(s) specified as <name>=<value> to pass into the
# template (the have higher priority than environment
# variables).
#
# OPTIONS:
# -d Don't evaluate template, just dump a shell script.
# -o <file> Output file or "-" for STDOUT. Defaults to "-".
# -s <shell> Command name or path of the shell to use for template
# evaluation. It must not contain spaces.
# Defaults to "/bin/sh".
# -h Show this help message and exit.
# -V Print version and exit.
#
# ENVIRONMENT:
# ESH_AWK Command name of path of the awk program to use.
# It must not contain spaces. Defaults to "awk".
# ESH_MAX_DEPTH Maximum include depth. Defaults to 3.
# ESH_SHELL Same as -s.
#
# EXIT STATUS:
# 0 Clean exit, no error has encountered.
# 1 Generic error.
# 10 Invalid usage.
# 11 ESH syntax error.
# 12 Include error: file not found.
# 13 Include error: exceeded max include depth (ESH_MAX_DEPTH).
#
# Please report bugs at <https://github.com/jirutka/esh/issues>.
#---help---
set -eu
readonly PROGNAME='esh'
readonly VERSION='0.3.0'
readonly SCRIPTPATH="$0"
AWK_CONVERTER=$(cat <<'AWK'
function fail(code, msg) {
state = "ERROR"
# FIXME: /dev/stderr is not portable
printf("%s: %s\n", line_info(), msg) > "/dev/stderr"
exit code
}
function line_info() {
return FILENAME ? (filenames[depth] ":" linenos[depth]) : "(init)" # (init) if inside BEGIN
}
# IMPORTANT: This is the only function that should print a newline.
function puts(str) {
print(line_info()) > MAP_FILE
print(str)
}
function fputs(str) {
printf("%s", str)
}
function trim(str) {
gsub(/^[ \t\r\n]+|[ \t\r\n]+$/, "", str)
return str
}
function read(len, _str) {
if (len == "") {
_str = buff
buff = ""
} else if (len > 0) {
_str = substr(buff, 1, len)
buff = substr(buff, len + 1, length(buff))
}
return _str
}
function skip(len) {
buff = substr(buff, len + 1, length(buff))
}
function flush(len, _str) {
_str = read(len)
if (state == "TEXT") {
gsub("'", "'\\''", _str)
}
if (state != "COMMENT") {
fputs(_str)
}
}
function file_exists(filename, _junk) {
if ((getline _junk < filename) >= 0) {
close(filename)
return 1
}
return 0
}
function dirname(path) {
return sub(/\/[^\/]+\/*$/, "/", path) ? path : ""
}
function include(filename) {
if (index(filename, "/") != 1) { # if does not start with "/"
filename = dirname(filenames[depth]) filename
}
if (!file_exists(filename)) {
fail(12, "cannot include " filename ": not a file or not readable")
}
if (depth > MAX_DEPTH) {
fail(13, "cannot include " filename ": exceeded maximum depth of " MAX_DEPTH)
}
buffs[depth] = buff
states[depth] = state
filenames[depth + 1] = filename
depth++
init()
while ((getline buff < filename) > 0) {
if (print_nl && state != "COMMENT") {
puts("")
}
process_line()
}
end_text()
close(filename)
depth--
buff = buffs[depth]
state = states[depth]
}
function init() {
buff = ""
linenos[depth] = 0
print_nl = 0
start_text()
}
function start_text() {
puts("")
fputs("printf '%s' '")
state = "TEXT"
}
function end_text() {
if (state != "TEXT") { return }
puts("' #< " line_info())
state = "UNDEF"
}
function process_line() {
linenos[depth]++
while (buff != "") {
print_nl = 1
if (state == "TEXT" && match(buff, /<%/)) {
flush(RSTART - 1) # print buff before "<%"
skip(2) # skip "<%"
flag = substr(buff, 1, 1)
if (flag != "%") {
end_text()
}
if (flag == "%") { # <%%
skip(1)
fputs("<%")
} else if (flag == "=") { # <%=
skip(1)
fputs("__print ")
state = "TAG"
} else if (flag == "+") { # <%+
if (!match(buff, /[^%]%>/)) {
fail(11, "syntax error: <%+ must be closed on the same line")
}
filename = trim(substr(buff, 2, match(buff, /.-?%>/) - 1))
skip(RSTART)
include(filename)
state = "TAG"
} else if (flag == "#") { # <%#
state = "COMMENT"
} else {
state = "TAG"
}
} else if (state != "TEXT" && match(buff, /%>/)) {
flag = RSTART > 1 ? substr(buff, RSTART - 1, 1) : ""
if (flag == "%") { # %%>
flush(RSTART - 2)
skip(1)
flush(2)
} else if (flag == "-") { # -%>
flush(RSTART - 2)
skip(3)
print_nl = 0
} else { # %>
flush(RSTART - 1)
skip(2)
}
if (flag != "%") {
start_text()
}
} else {
flush()
}
}
}
BEGIN {
FS = ""
depth = 0
puts("#!" (SHELL ~ /\// ? SHELL : "/usr/bin/env " SHELL))
puts("set -eu")
puts("if ( set -o pipefail 2>/dev/null ); then set -o pipefail; fi")
puts("__print() { printf '%s' \"$*\"; }")
split(VARS, _lines, /\n/)
for (_i in _lines) {
puts(_lines[_i])
}
init()
}
{
if (NR == 1) {
filenames[0] = FILENAME # this var is not defined in BEGIN so we must do it here
}
buff = $0
process_line()
if (print_nl && state != "COMMENT") {
puts("")
}
}
END {
end_text()
}
AWK
)
AWK_ERR_FILTER=$(cat <<'AWK'
function line_info(lno, _line, _i) {
while ((getline _line < MAPFILE) > 0 && _i++ < lno) { }
close(MAPFILE)
return _line
}
{
if (match($0, "^" SRCFILE ":( line)? ?[0-9]+:") && match(substr($0, 1, RLENGTH), /[0-9]+:$/)) {
lno = substr($0, RSTART, RLENGTH - 1) + 0
msg = substr($0, RSTART + RLENGTH + 1) # v-- some shells duplicate filename
msg = index(msg, SRCFILE ":") == 1 ? substr(msg, length(SRCFILE) + 3) : msg
print(line_info(lno) ": " msg)
} else if ($0 != "") {
print($0)
}
}
AWK
)
readonly AWK_CONVERTER AWK_ERR_FILTER
print_help() {
sed -En '/^#---help---/,/^#---help---/p' "$SCRIPTPATH" | sed -E 's/^# ?//; 1d;$d;'
}
filter_shell_stderr() {
$ESH_AWK \
-v SRCFILE="$1" \
-v MAPFILE="$2" \
-- "$AWK_ERR_FILTER"
}
evaluate() {
local srcfile="$1"
local mapfile="$2"
# This FD redirection magic is for swapping stdout/stderr back and forth.
exec 3>&1
{ set +e; $ESH_SHELL "$srcfile" 2>&1 1>&3; echo $? >>"$mapfile"; } \
| filter_shell_stderr "$srcfile" "$mapfile" >&2
exec 3>&-
return $(tail -n 1 "$mapfile")
}
convert() {
local input="$1"
local vars="$2"
local map_file="${3:-"/dev/null"}"
$ESH_AWK \
-v MAX_DEPTH="$ESH_MAX_DEPTH" \
-v SHELL="$ESH_SHELL" \
-v MAP_FILE="$map_file" \
-v VARS="$vars" \
-- "$AWK_CONVERTER" "$input"
}
process() {
local input="$1"
local vars="$2"
local evaluate="${3:-yes}"
local ret=0 tmpfile mapfile
if [ "$evaluate" = yes ]; then
tmpfile=$(mktemp)
mapfile=$(mktemp)
convert "$input" "$vars" "$mapfile" > "$tmpfile" || ret=$?
test $ret -ne 0 || evaluate "$tmpfile" "$mapfile" || ret=$?
rm -f "$tmpfile" "$mapfile"
else
convert "$input" "$vars" || ret=$?
fi
return $ret
}
: ${ESH_AWK:="awk"}
: ${ESH_MAX_DEPTH:=3}
: ${ESH_SHELL:="/bin/sh"}
EVALUATE='yes'
OUTPUT=''
while getopts ':dho:s:V' OPT; do
case "$OPT" in
d) EVALUATE=no;;
h) print_help; exit 0;;
o) OUTPUT="$OPTARG";;
s) ESH_SHELL="$OPTARG";;
V) echo "$PROGNAME $VERSION"; exit 0;;
'?') echo "$PROGNAME: unknown option: -$OPTARG" >&2; exit 10;;
esac
done
shift $(( OPTIND - 1 ))
if [ $# -eq 0 ]; then
printf "$PROGNAME: %s\n\n" 'missing argument <input>' >&2
print_help >&2
exit 10
fi
INPUT="$1"; shift
[ "$INPUT" != '-' ] || INPUT=''
if [ "$INPUT" ] && ! [ -f "$INPUT" -a -r "$INPUT" ]; then
echo "$PROGNAME: can't read $INPUT: not a file or not readable" >&2; exit 10
fi
# Validate arguments.
for arg in "$@"; do
case "$arg" in
*=*) ;;
*) echo "$PROGNAME: illegal argument: $arg" >&2; exit 10;;
esac
done
# Format variables into shell variable assignments.
vars=''; for item in "$@"; do
vars="$vars\n${item%%=*}='$(
printf %s "${item#*=}" | $ESH_AWK "{ gsub(/'/, \"'\\\\\\\''\"); print }"
)'"
done
export ESH="$0"
if [ "${OUTPUT#-}" ]; then
tmpfile="$(mktemp)"
trap "rm -f '$tmpfile'" EXIT HUP INT TERM
process "$INPUT" "$vars" "$EVALUATE" > "$tmpfile"
mv "$tmpfile" "$OUTPUT"
else
process "$INPUT" "$vars" "$EVALUATE"
fi

2
gitea/assets/gitea.service

@ -19,6 +19,8 @@ WorkingDirectory=/var/lib/gitea/
# If using Unix socket: tells systemd to create the /run/gitea folder, which will contain the gitea.sock file
# (manually creating /run/gitea doesn't work, because it would not persist across reboots)
#RuntimeDirectory=gitea
ExecStartPre=/usr/local/bin/esh /etc/gitea/app.ini.esh
ExecStartPre=/usr/local/bin/gitea --config /etc/gitea/app.ini admin regenerate keys
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
Restart=always
Environment=USER=gitea HOME=/var/lib/gitea GITEA_WORK_DIR=/var/lib/gitea

32
gitea/assets/sshd_config

@ -0,0 +1,32 @@
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
# Listening:
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
# Host Keys:
HostKey /etc/ssh/keys/ssh_host_rsa_key
HostKey /etc/ssh/keys/ssh_host_ecdsa_key
HostKey /etc/ssh/keys/ssh_host_ed25519_key
# Authentication:
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
# Settings:
X11Forwarding no
PrintMotd no
# Allow client to pass locale environment variables
AcceptEnv LANG LC_*
# override default of no subsystems
Subsystem sftp /usr/lib/openssh/sftp-server

2
gitea/docs/Build.md

@ -106,7 +106,7 @@ ROOT = /srv/gitea/repos
SSH_DOMAIN = localhost
DOMAIN = localhost
HTTP_PORT = 3000
ROOT_URL = http://medusa.casa.alemor.org/git/
ROOT_URL = https://${host_url}/
DISABLE_SSH = true
LFS_START_SERVER = true
LFS_CONTENT_PATH = /srv/gitea/lfs

4
mailsrv/assets/bin/mkvirt

@ -1,5 +1,9 @@
#!/bin/sh
### Domains ###
# /vol/data/domains should contain the configuration parameters for myhostname and virtual_alias_domains
cat /vol/data/domains /etc/postfix/main.cf.part > /etc/postfix/main.cf
### Users ###
# copy users db to dovecot config

4
mailsrv/assets/postfix/main.cf → mailsrv/assets/postfix/main.cf.part

@ -2,8 +2,6 @@
# interfaces & protocols to listen on
inet_interfaces = all
inet_protocols = all
# primary name of server
myhostname = mail.alemor.org
myorigin = $mydomain
# what host to use as a relay
relayhost =
@ -13,8 +11,6 @@ relayhost =
mynetworks_style = host
# domains to consider primary (local) endpoints
mydestination = $myhostname, $mydomain, localhost.localdomain, localhost
# domains to consider secondary (virtual) endpoints
virtual_alias_domains = epic.alemor.org, home.alemor.org, alegre.alemor.org, daniel.alemor.org, fernando.alemor.org, juana.alemor.org, mario.alemor.org, moreno.alemor.org, mar.alemor.org
### Users ###
# get list of valid users from here instead of /etc/passwd

6
mailsrv/docs/Deploy.md

@ -57,15 +57,15 @@ git clone https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install --home /usr/local/lib/acme-sh \
--config-home /etc/acme-sh \
--accountemail letsencrypt@mail.alemor.org
--accountemail ${email:?}
```
Then exit and relogin to refresh the bash hash
```
acme.sh --issue --alpn --pre-hook 'systemctl stop haproxy' \
--post-hook 'systemctl start haproxy' -d mail.alemor.org
acme.sh --install-cert -d mail.alemor.org \
--post-hook 'systemctl start haproxy' -d ${domain:?}
acme.sh --install-cert -d ${domain:?} \
--fullchain-file /srv/vol/mailsrv/ssl/fullchain.pem \
--key-file /srv/vol/mailsrv/ssl/privkey.pem
```

Loading…
Cancel
Save