@@ -0,0 +1,34 @@
|
||||
[Unit]
|
||||
# Description is a human-readable name for the service.
|
||||
Description=Gardomatic API service
|
||||
|
||||
# Wait until PostgreSQL is running and the network is "up" before starting the service.
|
||||
After=postgresql.service
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
# Configure service start rate limiting. If the service is (re)started more than 5 times
|
||||
# in 600 seconds then don't permit it to start anymore.
|
||||
StartLimitIntervalSec=600
|
||||
StartLimitBurst=5
|
||||
|
||||
[Service]
|
||||
# Execute the API binary as the gardomatic user, loading its dedicated environment file
|
||||
# and using its writable state directory.
|
||||
Type=exec
|
||||
User=gardomatic
|
||||
Group=gardomatic
|
||||
EnvironmentFile=/etc/gardomatic/gardomatic.env
|
||||
WorkingDirectory=/var/lib/gardomatic
|
||||
ExecStart=/usr/local/bin/gardomatic-api
|
||||
|
||||
# Automatically restart the service after a 5-second wait if it exits with a non-zero
|
||||
# exit code. If it restarts more than 5 times in 600 seconds, then the rate limit we
|
||||
# configured above will be hit and it won't be restarted anymore.
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
# Start the service automatically at boot time (the 'multi-user.target' describes a boot
|
||||
# state when the system will accept logins).
|
||||
WantedBy=multi-user.target
|
||||
Executable
+66
@@ -0,0 +1,66 @@
|
||||
#!/bin/bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
# Installs artifacts uploaded by `make production/deploy`. Run as root or as an
|
||||
# administrator with passwordless sudo.
|
||||
if [[ $(id -u) -ne 0 ]]; then
|
||||
exec sudo -n "$0" "$@"
|
||||
fi
|
||||
|
||||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
||||
APPLICATION_DIR=/opt/gardomatic
|
||||
STATE_DIR=/var/lib/gardomatic
|
||||
ENV_FILE=/etc/gardomatic/gardomatic.env
|
||||
|
||||
required_files=(
|
||||
api
|
||||
web
|
||||
cli
|
||||
api.service
|
||||
web.service
|
||||
create-admin.sh
|
||||
)
|
||||
for file in "${required_files[@]}"; do
|
||||
[[ -f "$SCRIPT_DIR/$file" ]] || {
|
||||
printf 'Missing deployment artifact: %s\n' "$file" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
[[ -d "$SCRIPT_DIR/migrations" ]] || {
|
||||
printf 'Missing deployment artifact: migrations\n' >&2
|
||||
exit 1
|
||||
}
|
||||
[[ -f "$ENV_FILE" ]] || {
|
||||
printf 'Missing runtime configuration: %s; run production/provision first.\n' "$ENV_FILE" >&2
|
||||
exit 1
|
||||
}
|
||||
id gardomatic >/dev/null 2>&1 || {
|
||||
printf 'Missing service user gardomatic; run production/provision first.\n' >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
install -d -m 0755 -o root -g root "$APPLICATION_DIR"
|
||||
install -d -m 0750 -o gardomatic -g gardomatic "$STATE_DIR"
|
||||
install -m 0755 -o root -g root "$SCRIPT_DIR/api" /usr/local/bin/gardomatic-api
|
||||
install -m 0755 -o root -g root "$SCRIPT_DIR/web" /usr/local/bin/gardomatic-web
|
||||
install -m 0755 -o root -g root "$SCRIPT_DIR/cli" /usr/local/bin/gardomatic-cli
|
||||
install -d -m 0755 -o root -g root "$APPLICATION_DIR/migrations"
|
||||
rsync --archive --delete "$SCRIPT_DIR/migrations/" "$APPLICATION_DIR/migrations/"
|
||||
|
||||
install -m 0644 -o root -g root "$SCRIPT_DIR/api.service" /etc/systemd/system/api.service
|
||||
install -m 0644 -o root -g root "$SCRIPT_DIR/web.service" /etc/systemd/system/web.service
|
||||
install -m 0755 -o root -g root "$SCRIPT_DIR/create-admin.sh" /usr/local/sbin/gardomatic-create-admin
|
||||
|
||||
# provision-server.sh writes a file compatible with systemd and Bash. Loading it
|
||||
# here keeps the database DSN out of command-line arguments and process listings.
|
||||
set -a
|
||||
# shellcheck disable=SC1091
|
||||
source "$ENV_FILE"
|
||||
set +a
|
||||
migrate -path "$APPLICATION_DIR/migrations" -database "$GARDOMATIC_DB_DSN" up
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable api web
|
||||
systemctl restart api web
|
||||
|
||||
printf 'Gardomatic deployment complete.\n'
|
||||
@@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
Description=Gardomatic web service
|
||||
After=network-online.target api.service
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=exec
|
||||
User=gardomatic
|
||||
Group=gardomatic
|
||||
EnvironmentFile=/etc/gardomatic/gardomatic.env
|
||||
WorkingDirectory=/var/lib/gardomatic
|
||||
ExecStart=/usr/local/bin/gardomatic-web
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,84 @@
|
||||
# Copy this file to .env next to provision-server.sh and restrict it to the
|
||||
# administrator. The file is sourced as Bash configuration and must be trusted.
|
||||
# cp .env.example .env
|
||||
# chmod 600 .env
|
||||
|
||||
# Server provisioning ---------------------------------------------------------
|
||||
|
||||
# IANA timezone accepted by timedatectl. List available values with:
|
||||
# timedatectl list-timezones
|
||||
GARDOMATIC_SETUP_TIMEZONE='Europe/Berlin'
|
||||
# golang-migrate release number without a leading "v". The script supports
|
||||
# Linux AMD64 and ARM64 release archives.
|
||||
GARDOMATIC_MIGRATE_VERSION='4.19.1'
|
||||
# Allowed exactly: true or false. false leaves rebooting to the administrator.
|
||||
GARDOMATIC_REBOOT='false'
|
||||
|
||||
# PostgreSQL provisioning -----------------------------------------------------
|
||||
|
||||
# Database and role names. Allowed: lowercase letters, digits and underscores;
|
||||
# the first character must be a letter or underscore.
|
||||
GARDOMATIC_DB_NAME='gardomatic'
|
||||
GARDOMATIC_DB_USER='gardomatic'
|
||||
# Required non-empty password used to create the PostgreSQL role. This separate
|
||||
# value is not installed in the service environment, but the DSN below is also a
|
||||
# secret because it normally contains the same password.
|
||||
GARDOMATIC_DB_PASSWORD=''
|
||||
|
||||
# Application runtime ---------------------------------------------------------
|
||||
|
||||
# Allowed: development, test, production. Keep production on public servers.
|
||||
GARDOMATIC_ENV='production'
|
||||
# Required PostgreSQL connection string. Percent-encode URI-reserved characters
|
||||
# in the password. Example form:
|
||||
# postgres://gardomatic:ENCODED_PASSWORD@localhost:5432/gardomatic?sslmode=disable
|
||||
GARDOMATIC_DB_DSN=''
|
||||
# Connection-pool limits. Open must be at least 1; idle must be between 0 and open.
|
||||
GARDOMATIC_DB_MAX_OPEN_CONNS='25'
|
||||
GARDOMATIC_DB_MAX_IDLE_CONNS='25'
|
||||
# Go duration, for example 30s, 15m or 1h30m.
|
||||
GARDOMATIC_DB_MAX_IDLE_TIME='15m'
|
||||
|
||||
# Listener hosts. Use 127.0.0.1 behind a reverse proxy; an empty value listens on
|
||||
# all available interfaces. Ports must be integers from 1 to 65535.
|
||||
GARDOMATIC_API_HOST='127.0.0.1'
|
||||
GARDOMATIC_API_PORT='4000'
|
||||
GARDOMATIC_WEB_HOST='127.0.0.1'
|
||||
GARDOMATIC_WEB_PORT='4040'
|
||||
# Absolute internal API URL used by the web process.
|
||||
GARDOMATIC_API_BASE_URL='http://127.0.0.1:4000'
|
||||
# Required absolute public HTTP(S) URL. Use HTTPS and normally no path in production.
|
||||
GARDOMATIC_WEB_BASE_URL=''
|
||||
|
||||
# Non-empty cookie name shared by API and web.
|
||||
GARDOMATIC_SESSION_COOKIE_NAME='gardomatic_session'
|
||||
# Go durations, for example 30m, 12h or 168h. Use positive values.
|
||||
GARDOMATIC_SESSION_LIFETIME='12h'
|
||||
GARDOMATIC_SESSION_IDLE_TIMEOUT='30m'
|
||||
# Boolean. Accepted true values: 1, t, T, TRUE, true, True. Accepted false
|
||||
# values: 0, f, F, FALSE, false, False. Must be true in production.
|
||||
GARDOMATIC_COOKIE_SECURE='true'
|
||||
|
||||
# Boolean with the same accepted forms as GARDOMATIC_COOKIE_SECURE.
|
||||
GARDOMATIC_RATE_LIMIT_ENABLED='true'
|
||||
# Positive requests per second; decimal values such as 0.5 are accepted.
|
||||
GARDOMATIC_RATE_LIMIT_RPS='10'
|
||||
# Positive integer defining the permitted request burst.
|
||||
GARDOMATIC_RATE_LIMIT_BURST='40'
|
||||
# Comma-separated absolute URLs; every entry requires a scheme and host. Empty
|
||||
# allows no cross-origin browser access. Use origins without paths, for example:
|
||||
# https://garden.example.com,https://admin.example.com
|
||||
GARDOMATIC_CORS_TRUSTED_ORIGINS=''
|
||||
|
||||
# Delivery mode. Allowed exactly: file or smtp. Production normally uses smtp.
|
||||
GARDOMATIC_SMTP_MODE='smtp'
|
||||
# Required in smtp mode: resolvable SMTP hostname and TCP port.
|
||||
GARDOMATIC_SMTP_HOST=''
|
||||
GARDOMATIC_SMTP_PORT='587'
|
||||
# Required non-empty credentials in smtp mode.
|
||||
GARDOMATIC_SMTP_USERNAME=''
|
||||
GARDOMATIC_SMTP_PASSWORD=''
|
||||
# Required sender mailbox in smtp mode, for example gardomatic@example.com.
|
||||
GARDOMATIC_SMTP_SENDER=''
|
||||
# Writable absolute path required only when GARDOMATIC_SMTP_MODE=file.
|
||||
GARDOMATIC_SMTP_FILE_PATH='/tmp/gardomatic-mails.log'
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
# Creates an active application administrator and prints a generated password
|
||||
# exactly once. Installed during deployment as gardomatic-create-admin.
|
||||
if [[ $(id -u) -ne 0 ]]; then
|
||||
exec sudo -n "$0" "$@"
|
||||
fi
|
||||
|
||||
ENV_FILE=/etc/gardomatic/gardomatic.env
|
||||
CLI=/usr/local/bin/gardomatic-cli
|
||||
|
||||
[[ -f "$ENV_FILE" ]] || {
|
||||
printf 'Missing runtime configuration: %s\n' "$ENV_FILE" >&2
|
||||
exit 1
|
||||
}
|
||||
[[ -x "$CLI" ]] || {
|
||||
printf 'Missing Gardomatic CLI: %s\n' "$CLI" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
read -r -p 'Administrator name: ' admin_name
|
||||
read -r -p 'Administrator email: ' admin_email
|
||||
[[ -n "$admin_name" && -n "$admin_email" ]] || {
|
||||
printf 'Name and email must not be empty.\n' >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
set -a
|
||||
# shellcheck disable=SC1091
|
||||
source "$ENV_FILE"
|
||||
set +a
|
||||
|
||||
"$CLI" --yes users create \
|
||||
--name "$admin_name" \
|
||||
--email "$admin_email" \
|
||||
--role application:admin \
|
||||
--active \
|
||||
--generate-password
|
||||
Executable
+242
@@ -0,0 +1,242 @@
|
||||
#!/bin/bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
# Run this script as root or as an administrator with passwordless sudo.
|
||||
# Configuration is read from a trusted shell-style .env file or standard input.
|
||||
|
||||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
||||
ENV_FILE="${SCRIPT_DIR}/.env"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: ./provision-server.sh [--env-file PATH|-]
|
||||
|
||||
Provision the Gardomatic server and install its runtime configuration.
|
||||
The default configuration file is .env next to this script. Use - to stream the
|
||||
configuration over SSH without storing the source file on the server.
|
||||
EOF
|
||||
}
|
||||
|
||||
die() {
|
||||
printf 'Error: %s\n' "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
while (($# > 0)); do
|
||||
case "$1" in
|
||||
--env-file)
|
||||
(($# >= 2)) || die "--env-file requires a path"
|
||||
ENV_FILE=$2
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
die "unknown argument: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "$ENV_FILE" == - ]]; then
|
||||
ENV_SOURCE=/dev/stdin
|
||||
ENV_LABEL='standard input'
|
||||
else
|
||||
[[ -f "$ENV_FILE" ]] || die "configuration file not found: $ENV_FILE"
|
||||
env_permissions=$(stat -c '%a' "$ENV_FILE")
|
||||
(( (8#$env_permissions & 077) == 0 )) || die "$ENV_FILE must not be readable or writable by group or others (run: chmod 600 '$ENV_FILE')"
|
||||
ENV_SOURCE=$ENV_FILE
|
||||
ENV_LABEL=$ENV_FILE
|
||||
fi
|
||||
|
||||
# The file is deliberately sourced so quoted values work. It must therefore be
|
||||
# controlled by the administrator running this script.
|
||||
set -a
|
||||
# shellcheck disable=SC1090
|
||||
source "$ENV_SOURCE"
|
||||
set +a
|
||||
|
||||
require_variable() {
|
||||
local name=$1
|
||||
[[ -n "${!name:-}" ]] || die "required variable $name is missing in $ENV_LABEL"
|
||||
}
|
||||
|
||||
require_identifier() {
|
||||
local name=$1
|
||||
local value=${!name:-}
|
||||
[[ "$value" =~ ^[a-z_][a-z0-9_]*$ ]] || die "$name must be a lowercase PostgreSQL identifier"
|
||||
}
|
||||
|
||||
require_variable GARDOMATIC_DB_PASSWORD
|
||||
require_variable GARDOMATIC_DB_DSN
|
||||
require_variable GARDOMATIC_WEB_BASE_URL
|
||||
require_identifier GARDOMATIC_DB_NAME
|
||||
require_identifier GARDOMATIC_DB_USER
|
||||
|
||||
case "${GARDOMATIC_SMTP_MODE:-file}" in
|
||||
smtp)
|
||||
require_variable GARDOMATIC_SMTP_HOST
|
||||
require_variable GARDOMATIC_SMTP_USERNAME
|
||||
require_variable GARDOMATIC_SMTP_PASSWORD
|
||||
require_variable GARDOMATIC_SMTP_SENDER
|
||||
;;
|
||||
file)
|
||||
require_variable GARDOMATIC_SMTP_FILE_PATH
|
||||
;;
|
||||
*)
|
||||
die "GARDOMATIC_SMTP_MODE must be smtp or file"
|
||||
;;
|
||||
esac
|
||||
|
||||
GARDOMATIC_SETUP_TIMEZONE=${GARDOMATIC_SETUP_TIMEZONE:-Europe/Berlin}
|
||||
GARDOMATIC_MIGRATE_VERSION=${GARDOMATIC_MIGRATE_VERSION:-4.19.1}
|
||||
GARDOMATIC_REBOOT=${GARDOMATIC_REBOOT:-false}
|
||||
[[ "$GARDOMATIC_REBOOT" == true || "$GARDOMATIC_REBOOT" == false ]] || die "GARDOMATIC_REBOOT must be true or false"
|
||||
|
||||
readonly GARDOMATIC_SERVICE_USER=gardomatic
|
||||
|
||||
run_as_root() {
|
||||
if [[ $(id -u) -eq 0 ]]; then
|
||||
"$@"
|
||||
else
|
||||
sudo -n "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
run_as_postgres() {
|
||||
if [[ $(id -u) -eq 0 ]]; then
|
||||
runuser -u postgres -- "$@"
|
||||
else
|
||||
sudo -n -u postgres "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ $(id -u) -ne 0 ]]; then
|
||||
sudo -n true || die "the SSH administrator needs passwordless sudo"
|
||||
fi
|
||||
|
||||
# Force consistent command output while locales are being installed.
|
||||
export LC_ALL=en_US.UTF-8
|
||||
|
||||
run_as_root apt update
|
||||
run_as_root apt install --yes software-properties-common locales curl rsync ufw
|
||||
run_as_root add-apt-repository --yes universe
|
||||
run_as_root apt update
|
||||
run_as_root timedatectl set-timezone "$GARDOMATIC_SETUP_TIMEZONE"
|
||||
run_as_root apt --yes install locales-all
|
||||
|
||||
# Gardomatic runs under a dedicated service account. It has no login shell, SSH
|
||||
# keys, password or sudo privileges; deployments continue through the configured
|
||||
# server administrator account.
|
||||
if id "$GARDOMATIC_SERVICE_USER" >/dev/null 2>&1; then
|
||||
if ! getent group "$GARDOMATIC_SERVICE_USER" >/dev/null 2>&1; then
|
||||
run_as_root groupadd --system "$GARDOMATIC_SERVICE_USER"
|
||||
fi
|
||||
run_as_root usermod --lock --shell /usr/sbin/nologin "$GARDOMATIC_SERVICE_USER"
|
||||
run_as_root usermod --gid "$GARDOMATIC_SERVICE_USER" "$GARDOMATIC_SERVICE_USER"
|
||||
run_as_root deluser --quiet "$GARDOMATIC_SERVICE_USER" sudo >/dev/null 2>&1 || true
|
||||
else
|
||||
run_as_root useradd --system --user-group --create-home --home-dir /var/lib/gardomatic \
|
||||
--shell /usr/sbin/nologin "$GARDOMATIC_SERVICE_USER"
|
||||
fi
|
||||
run_as_root install -d -m 0750 -o gardomatic -g gardomatic /var/lib/gardomatic
|
||||
|
||||
run_as_root ufw allow 22
|
||||
run_as_root ufw allow 4040/tcp
|
||||
run_as_root ufw --force enable
|
||||
run_as_root apt --yes install fail2ban
|
||||
|
||||
# Install the migrate CLI for the host architecture.
|
||||
case "$(uname -m)" in
|
||||
x86_64|amd64) migrate_arch=amd64 ;;
|
||||
aarch64|arm64) migrate_arch=arm64 ;;
|
||||
*) die "unsupported architecture for migrate: $(uname -m)" ;;
|
||||
esac
|
||||
|
||||
download_dir=$(mktemp -d)
|
||||
runtime_env=$(mktemp)
|
||||
cleanup() {
|
||||
rm -rf -- "$download_dir"
|
||||
rm -f -- "$runtime_env"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
migrate_archive="$download_dir/migrate.tar.gz"
|
||||
curl --fail --location --show-error \
|
||||
"https://github.com/golang-migrate/migrate/releases/download/v${GARDOMATIC_MIGRATE_VERSION}/migrate.linux-${migrate_arch}.tar.gz" \
|
||||
--output "$migrate_archive"
|
||||
tar -xzf "$migrate_archive" -C "$download_dir"
|
||||
run_as_root install -m 0755 "$download_dir/migrate" /usr/local/bin/migrate
|
||||
|
||||
run_as_root apt --yes install postgresql postgresql-contrib
|
||||
|
||||
if ! run_as_postgres psql -tAc "SELECT 1 FROM pg_database WHERE datname = '${GARDOMATIC_DB_NAME}'" | grep -qx 1; then
|
||||
run_as_postgres createdb "$GARDOMATIC_DB_NAME"
|
||||
fi
|
||||
run_as_postgres psql -d "$GARDOMATIC_DB_NAME" -c "CREATE EXTENSION IF NOT EXISTS citext"
|
||||
run_as_postgres psql -d "$GARDOMATIC_DB_NAME" -c "CREATE EXTENSION IF NOT EXISTS pgcrypto"
|
||||
if ! run_as_postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname = '${GARDOMATIC_DB_USER}'" | grep -qx 1; then
|
||||
printf '%s\n' "CREATE ROLE \"${GARDOMATIC_DB_USER}\" WITH LOGIN PASSWORD :'db_password';" | \
|
||||
run_as_postgres psql -v db_password="$GARDOMATIC_DB_PASSWORD"
|
||||
else
|
||||
printf '%s\n' "ALTER ROLE \"${GARDOMATIC_DB_USER}\" WITH LOGIN PASSWORD :'db_password';" | \
|
||||
run_as_postgres psql -v db_password="$GARDOMATIC_DB_PASSWORD"
|
||||
fi
|
||||
run_as_postgres psql -c "ALTER DATABASE \"${GARDOMATIC_DB_NAME}\" OWNER TO \"${GARDOMATIC_DB_USER}\";"
|
||||
|
||||
# Generate a dedicated systemd environment file. Setup-only values such as the
|
||||
# raw database password are intentionally not copied into the service environment.
|
||||
write_environment_variable() {
|
||||
local name=$1
|
||||
local value=${!name:-}
|
||||
[[ "$value" != *$'\n'* && "$value" != *$'\r'* ]] || die "$name must not contain newlines"
|
||||
value=${value//\\/\\\\}
|
||||
value=${value//\"/\\\"}
|
||||
value=${value//\$/\\$}
|
||||
value=${value//\`/\\\`}
|
||||
printf '%s="%s"\n' "$name" "$value" >>"$runtime_env"
|
||||
}
|
||||
|
||||
runtime_variables=(
|
||||
GARDOMATIC_ENV
|
||||
GARDOMATIC_DB_DSN
|
||||
GARDOMATIC_DB_MAX_OPEN_CONNS
|
||||
GARDOMATIC_DB_MAX_IDLE_CONNS
|
||||
GARDOMATIC_DB_MAX_IDLE_TIME
|
||||
GARDOMATIC_API_HOST
|
||||
GARDOMATIC_API_PORT
|
||||
GARDOMATIC_WEB_HOST
|
||||
GARDOMATIC_WEB_PORT
|
||||
GARDOMATIC_API_BASE_URL
|
||||
GARDOMATIC_WEB_BASE_URL
|
||||
GARDOMATIC_SESSION_COOKIE_NAME
|
||||
GARDOMATIC_SESSION_LIFETIME
|
||||
GARDOMATIC_SESSION_IDLE_TIMEOUT
|
||||
GARDOMATIC_COOKIE_SECURE
|
||||
GARDOMATIC_RATE_LIMIT_ENABLED
|
||||
GARDOMATIC_RATE_LIMIT_RPS
|
||||
GARDOMATIC_RATE_LIMIT_BURST
|
||||
GARDOMATIC_CORS_TRUSTED_ORIGINS
|
||||
GARDOMATIC_SMTP_MODE
|
||||
GARDOMATIC_SMTP_HOST
|
||||
GARDOMATIC_SMTP_PORT
|
||||
GARDOMATIC_SMTP_USERNAME
|
||||
GARDOMATIC_SMTP_PASSWORD
|
||||
GARDOMATIC_SMTP_SENDER
|
||||
GARDOMATIC_SMTP_FILE_PATH
|
||||
)
|
||||
for variable in "${runtime_variables[@]}"; do
|
||||
write_environment_variable "$variable"
|
||||
done
|
||||
|
||||
run_as_root install -D -m 0600 -o root -g root "$runtime_env" /etc/gardomatic/gardomatic.env
|
||||
|
||||
run_as_root apt --yes -o Dpkg::Options::="--force-confnew" upgrade
|
||||
|
||||
printf 'Server setup complete. Runtime configuration installed at /etc/gardomatic/gardomatic.env.\n'
|
||||
if [[ "$GARDOMATIC_REBOOT" == true ]]; then
|
||||
run_as_root reboot
|
||||
else
|
||||
printf 'Reboot skipped. Set GARDOMATIC_REBOOT=true in %s to reboot automatically.\n' "$ENV_LABEL"
|
||||
fi
|
||||
Reference in New Issue
Block a user