Skip to content

Commit

Permalink
Don't write config envs to file, check for links not files
Browse files Browse the repository at this point in the history
  • Loading branch information
thespad committed Jan 24, 2024
1 parent 2e4c6f7 commit 71de43f
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 156 deletions.
77 changes: 40 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Find us at:

[Healthchecks](https://github.com/healthchecks/healthchecks) is a watchdog for your cron jobs. It's a web server that listens for pings from your cron jobs, plus a web interface.

[![healthchecks](https://raw.githubusercontent.com/healthchecks/healthchecks/master/static/img/welcome.png)](https://github.com/healthchecks/healthchecks)
[![healthchecks](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/healthchecks-logo.png")](https://github.com/healthchecks/healthchecks)

## Supported Architectures

Expand All @@ -61,6 +61,8 @@ The architectures supported by this image are:

Access the WebUI at <your-ip>:8000. For more information, check out [Healthchecks](https://github.com/healthchecks/healthchecks).

See [here](https://healthchecks.io/docs/self_hosted_configuration/) for a complete list of available environment variables.

## Usage

To help you get started creating a container from this image you can either use docker-compose or the docker cli.
Expand All @@ -79,21 +81,21 @@ services:
- TZ=Etc/UTC
- SITE_ROOT=
- SITE_NAME=
- DEFAULT_FROM_EMAIL=
- EMAIL_HOST=
- EMAIL_PORT=
- EMAIL_HOST_USER=
- EMAIL_HOST_PASSWORD=
- EMAIL_USE_TLS=
- SUPERUSER_EMAIL=
- SUPERUSER_PASSWORD=
- REGENERATE_SETTINGS= #optional
- ALLOWED_HOSTS= #optional
- APPRISE_ENABLED=False #optional
- CSRF_TRUSTED_ORIGINS= #optional
- APPRISE_ENABLED= #optional
- DEBUG= #optional
- DEBUG=True #optional
- DEFAULT_FROM_EMAIL= #optional
- EMAIL_HOST= #optional
- EMAIL_PORT= #optional
- EMAIL_HOST_USER= #optional
- EMAIL_HOST_PASSWORD= #optional
- EMAIL_USE_TLS= #optional
- INTEGRATIONS_ALLOW_PRIVATE_IPS= #optional
- PING_EMAIL_DOMAIN= #optional
- RP_ID= #optional
- SECRET_KEY= #optional
- SITE_LOGO_URL= #optional
volumes:
Expand All @@ -114,21 +116,21 @@ docker run -d \
-e TZ=Etc/UTC \
-e SITE_ROOT= \
-e SITE_NAME= \
-e DEFAULT_FROM_EMAIL= \
-e EMAIL_HOST= \
-e EMAIL_PORT= \
-e EMAIL_HOST_USER= \
-e EMAIL_HOST_PASSWORD= \
-e EMAIL_USE_TLS= \
-e SUPERUSER_EMAIL= \
-e SUPERUSER_PASSWORD= \
-e REGENERATE_SETTINGS= `#optional` \
-e ALLOWED_HOSTS= `#optional` \
-e APPRISE_ENABLED=False `#optional` \
-e CSRF_TRUSTED_ORIGINS= `#optional` \
-e APPRISE_ENABLED= `#optional` \
-e DEBUG= `#optional` \
-e DEBUG=True `#optional` \
-e DEFAULT_FROM_EMAIL= `#optional` \
-e EMAIL_HOST= `#optional` \
-e EMAIL_PORT= `#optional` \
-e EMAIL_HOST_USER= `#optional` \
-e EMAIL_HOST_PASSWORD= `#optional` \
-e EMAIL_USE_TLS= `#optional` \
-e INTEGRATIONS_ALLOW_PRIVATE_IPS= `#optional` \
-e PING_EMAIL_DOMAIN= `#optional` \
-e RP_ID= `#optional` \
-e SECRET_KEY= `#optional` \
-e SITE_LOGO_URL= `#optional` \
-p 8000:8000 \
Expand All @@ -149,26 +151,26 @@ Containers are configured using parameters passed at runtime (such as those abov
| `-e PUID=1000` | for UserID - see below for explanation |
| `-e PGID=1000` | for GroupID - see below for explanation |
| `-e TZ=Etc/UTC` | specify a timezone to use, see this [list](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List). |
| `-e SITE_ROOT=` | The site's top-level URL and the port it listens to if differrent than 80 or 443 (e.g., https://healthchecks.example.com:8000) |
| `-e SITE_NAME=` | The site's name (e.g., "Example Corp HealthChecks") |
| `-e DEFAULT_FROM_EMAIL=` | From email for alerts |
| `-e EMAIL_HOST=` | SMTP host |
| `-e EMAIL_PORT=` | SMTP port |
| `-e EMAIL_HOST_USER=` | SMTP user |
| `-e EMAIL_HOST_PASSWORD=` | SMTP password |
| `-e EMAIL_USE_TLS=` | Use TLS for SMTP (`True` or `False`) |
| `-e SUPERUSER_EMAIL=` | Superuser email |
| `-e SUPERUSER_PASSWORD=` | Superuser password |
| `-e REGENERATE_SETTINGS=` | Defaults to False. Set to True to always override the `local_settings.py` file with values from environment variables. Do not set to True if you have made manual modifications to this file. |
| `-e ALLOWED_HOSTS=` | A [list](https://docs.python.org/3/tutorial/introduction.html#lists) of valid hostnames for the server. Default is: `["*"]` |
| `-e SITE_ROOT=` | The site's top-level URL and the port it listens to if different than 80 or 443 (e.g., https://healthchecks.example.com:8000). |
| `-e SITE_NAME=` | The site's name (e.g., "Example Corp HealthChecks"). |
| `-e SUPERUSER_EMAIL=` | Superuser email. |
| `-e SUPERUSER_PASSWORD=` | Superuser password. |
| `-e ALLOWED_HOSTS=` | A [list](https://docs.python.org/3/tutorial/introduction.html#lists) of valid hostnames for the server. Default is: `["*"]`. |
| `-e APPRISE_ENABLED=False` | Set to `True` to enable the Apprise integration (https://github.com/caronc/apprise). |
| `-e CSRF_TRUSTED_ORIGINS=` | A [list](https://docs.python.org/3/tutorial/introduction.html#lists) of trusted origins for unsafe requests (e.g. POST). Defaults to the value of `SITE_ROOT`. |
| `-e APPRISE_ENABLED=` | Defaults to False. A boolean that turns on/off the Apprise integration (https://github.com/caronc/apprise) |
| `-e DEBUG=` | Defaults to True. Debug mode relaxes CSRF protections and increases logging verbosity but should be disabled for production instances as it will impact performance and security. |
| `-e DEBUG=True` | Set to `False` to disable. Debug mode relaxes CSRF protections and increases logging verbosity but should be disabled for production instances as it will impact performance and security. |
| `-e DEFAULT_FROM_EMAIL=` | From email for alerts. |
| `-e EMAIL_HOST=` | SMTP host. |
| `-e EMAIL_PORT=` | SMTP port. |
| `-e EMAIL_HOST_USER=` | SMTP user. |
| `-e EMAIL_HOST_PASSWORD=` | SMTP password. |
| `-e EMAIL_USE_TLS=` | Use TLS for SMTP (`True` or `False`). |
| `-e INTEGRATIONS_ALLOW_PRIVATE_IPS=` | Defaults to False. Set to True to allow integrations to connect to private IP addresses. |
| `-e PING_EMAIL_DOMAIN=` | The domain to use for generating ping email addresses. |
| `-e SECRET_KEY=` | A secret key used for cryptographic signing. Will generate a secure value if one is not supplied |
| `-e SITE_LOGO_URL=` | Full URL to custom site logo |
| `-v /config` | Persistent config files |
| `-e PING_EMAIL_DOMAIN=` | The domain to use for generating ping email addresses. Defaults to `localhost`. |
| `-e RP_ID=` | If using webauthn for 2FA set this to match your Healthchecks domain. Webauthn will only work over https. |
| `-e SECRET_KEY=` | A secret key used for cryptographic signing. Will generate a random value if one is not supplied and save it to `/config/local_settings.py`. |
| `-e SITE_LOGO_URL=` | Full URL to custom site logo. |
| `-v /config` | Persistent config files. |

## Environment variables from files (Docker secrets)

Expand Down Expand Up @@ -331,6 +333,7 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64

## Versions

* **24.01.24:** - No longer write envs to local_settings.py. Envs will take precedence over any existing values in config file. Removed `REGENERATE_SETTINGS` as it is now obsolete.
* **22.01.24:** - Fix CSRF handling.
* **23.12.23:** - Rebase to Alpine 3.19.
* **31.05.23:** - Rebase to Alpine 3.18. Deprecate armhf.
Expand Down
41 changes: 22 additions & 19 deletions readme-vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# project information
project_name: healthchecks
project_url: "https://github.com/healthchecks/healthchecks"
project_logo: "https://raw.githubusercontent.com/healthchecks/healthchecks/master/static/img/welcome.png"
project_logo: https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/healthchecks-logo.png"
project_blurb: |
[{{ project_name|capitalize }}]({{ project_url }}) is a watchdog for your cron jobs. It's a web server that listens for pings from your cron jobs, plus a web interface.
project_lsio_github_repo_url: "https://github.com/linuxserver/docker-{{ project_name }}"
Expand All @@ -17,30 +17,30 @@ available_architectures:
param_container_name: "{{ project_name }}"
param_usage_include_vols: true
param_volumes:
- { vol_path: "/config", vol_host_path: "/path/to/{{ project_name }}/config", desc: "Persistent config files" }
- { vol_path: "/config", vol_host_path: "/path/to/{{ project_name }}/config", desc: "Persistent config files." }
param_usage_include_env: true
param_env_vars:
- { env_var: "SITE_ROOT", env_value: "", desc: "The site's top-level URL and the port it listens to if differrent than 80 or 443 (e.g., https://healthchecks.example.com:8000)" }
- { env_var: "SITE_NAME", env_value: "", desc: "The site's name (e.g., \"Example Corp HealthChecks\")"}
- { env_var: "DEFAULT_FROM_EMAIL", env_value: "", desc: "From email for alerts" }
- { env_var: "EMAIL_HOST", env_value: "", desc: "SMTP host" }
- { env_var: "EMAIL_PORT", env_value: "", desc: "SMTP port"}
- { env_var: "EMAIL_HOST_USER", env_value: "", desc: "SMTP user"}
- { env_var: "EMAIL_HOST_PASSWORD", env_value: "", desc: "SMTP password"}
- { env_var: "EMAIL_USE_TLS", env_value: "", desc: "Use TLS for SMTP (`True` or `False`)"}
- { env_var: "SUPERUSER_EMAIL", env_value: "", desc: "Superuser email"}
- { env_var: "SUPERUSER_PASSWORD", env_value: "", desc: "Superuser password"}
- { env_var: "SITE_ROOT", env_value: "", desc: "The site's top-level URL and the port it listens to if different than 80 or 443 (e.g., https://healthchecks.example.com:8000)." }
- { env_var: "SITE_NAME", env_value: "", desc: "The site's name (e.g., \"Example Corp HealthChecks\")."}
- { env_var: "SUPERUSER_EMAIL", env_value: "", desc: "Superuser email."}
- { env_var: "SUPERUSER_PASSWORD", env_value: "", desc: "Superuser password."}
opt_param_usage_include_env: true
opt_param_env_vars:
- { env_var: "REGENERATE_SETTINGS", env_value: "", desc: "Defaults to False. Set to True to always override the `local_settings.py` file with values from environment variables. Do not set to True if you have made manual modifications to this file."}
- { env_var: "ALLOWED_HOSTS", env_value: "", desc: "A [list](https://docs.python.org/3/tutorial/introduction.html#lists) of valid hostnames for the server. Default is: `[\"*\"]`"}
- { env_var: "ALLOWED_HOSTS", env_value: "", desc: "A [list](https://docs.python.org/3/tutorial/introduction.html#lists) of valid hostnames for the server. Default is: `[\"*\"]`."}
- { env_var: "APPRISE_ENABLED", env_value: "False", desc: "Set to `True` to enable the Apprise integration (https://github.com/caronc/apprise)." }
- { env_var: "CSRF_TRUSTED_ORIGINS", env_value: "", desc: "A [list](https://docs.python.org/3/tutorial/introduction.html#lists) of trusted origins for unsafe requests (e.g. POST). Defaults to the value of `SITE_ROOT`."}
- { env_var: "APPRISE_ENABLED", env_value: "", desc: "Defaults to False. A boolean that turns on/off the Apprise integration (https://github.com/caronc/apprise)" }
- { env_var: "DEBUG", env_value: "", desc: "Defaults to True. Debug mode relaxes CSRF protections and increases logging verbosity but should be disabled for production instances as it will impact performance and security."}
- { env_var: "DEBUG", env_value: "True", desc: "Set to `False` to disable. Debug mode relaxes CSRF protections and increases logging verbosity but should be disabled for production instances as it will impact performance and security."}
- { env_var: "DEFAULT_FROM_EMAIL", env_value: "", desc: "From email for alerts." }
- { env_var: "EMAIL_HOST", env_value: "", desc: "SMTP host." }
- { env_var: "EMAIL_PORT", env_value: "", desc: "SMTP port."}
- { env_var: "EMAIL_HOST_USER", env_value: "", desc: "SMTP user."}
- { env_var: "EMAIL_HOST_PASSWORD", env_value: "", desc: "SMTP password."}
- { env_var: "EMAIL_USE_TLS", env_value: "", desc: "Use TLS for SMTP (`True` or `False`)."}
- { env_var: "INTEGRATIONS_ALLOW_PRIVATE_IPS", env_value: "", desc: "Defaults to False. Set to True to allow integrations to connect to private IP addresses."}
- { env_var: "PING_EMAIL_DOMAIN", env_value: "", desc: "The domain to use for generating ping email addresses."}
- { env_var: "SECRET_KEY", env_value: "", desc: "A secret key used for cryptographic signing. Will generate a secure value if one is not supplied" }
- { env_var: "SITE_LOGO_URL", env_value: "", desc: "Full URL to custom site logo"}
- { env_var: "PING_EMAIL_DOMAIN", env_value: "", desc: "The domain to use for generating ping email addresses. Defaults to `localhost`."}
- { env_var: "RP_ID", env_value: "", desc: "If using webauthn for 2FA set this to match your Healthchecks domain. Webauthn will only work over https."}
- { env_var: "SECRET_KEY", env_value: "", desc: "A secret key used for cryptographic signing. Will generate a random value if one is not supplied and save it to `/config/local_settings.py`." }
- { env_var: "SITE_LOGO_URL", env_value: "", desc: "Full URL to custom site logo."}

param_usage_include_ports: true
param_ports:
Expand All @@ -54,8 +54,11 @@ app_setup_block_enabled: true
app_setup_block: |
Access the WebUI at <your-ip>:8000. For more information, check out [Healthchecks](https://github.com/healthchecks/healthchecks).
See [here](https://healthchecks.io/docs/self_hosted_configuration/) for a complete list of available environment variables.
# changelog
changelogs:
- { date: "24.01.24:", desc: "No longer write envs to local_settings.py. Envs will take precedence over any existing values in config file. Removed `REGENERATE_SETTINGS` as it is now obsolete."}
- { date: "22.01.24:", desc: "Fix CSRF handling."}
- { date: "23.12.23:", desc: "Rebase to Alpine 3.19."}
- { date: "31.05.23:", desc: "Rebase to Alpine 3.18. Deprecate armhf."}
Expand Down
113 changes: 13 additions & 100 deletions root/etc/s6-overlay/s6-rc.d/init-healthchecks-config/run
Original file line number Diff line number Diff line change
Expand Up @@ -4,82 +4,9 @@
lsiown -R abc:abc \
/app/healthchecks/hc/api/migrations

#From https://healthchecks.io/docs/self_hosted_configuration/
HC_CONF=(
ADMINS
ALLOWED_HOSTS
APPRISE_ENABLED
DEBUG
DEFAULT_FROM_EMAIL
DISCORD_CLIENT_ID
DISCORD_CLIENT_SECRET
EMAIL_HOST
EMAIL_HOST_PASSWORD
EMAIL_HOST_USER
EMAIL_PORT
EMAIL_USE_TLS
EMAIL_USE_VERIFICATION
INTEGRATIONS_ALLOW_PRIVATE_IPS
LINENOTIFY_CLIENT_ID
LINENOTIFY_CLIENT_SECRET
MASTER_BADGE_LABEL
MATRIX_ACCESS_TOKEN
MATRIX_HOMESERVER
MATRIX_USER_ID
MATTERMOST_ENABLED
MSTEAMS_ENABLED
OPSGENIE_ENABLED
PAGERTREE_ENABLED
PD_APP_ID
PD_ENABLED
PING_EMAIL_DOMAIN
PING_ENDPOINT
PROMETHEUS_ENABLED
PUSHBULLET_CLIENT_ID
PUSHBULLET_CLIENT_SECRET
PUSHOVER_API_TOKEN
PUSHOVER_EMERGENCY_EXPIRATION
PUSHOVER_EMERGENCY_RETRY_DELAY
PUSHOVER_SUBSCRIPTION_URL
REGISTRATION_OPEN
REMOTE_USER_HEADER
RP_ID
S3_ACCESS_KEY
S3_BUCKET
S3_ENDPOINT
S3_REGION
S3_SECRET_KEY
S3_TIMEOUT
SHELL_ENABLED
SIGNAL_CLI_ENABLED
SITE_LOGO_URL
SITE_NAME
SITE_ROOT
SLACK_CLIENT_ID
SLACK_CLIENT_SECRET
SLACK_ENABLED
SPIKE_ENABLED
TELEGRAM_BOT_NAME
TELEGRAM_TOKEN
TRELLO_APP_KEY
TWILIO_ACCOUNT
TWILIO_AUTH
TWILIO_FROM
TWILIO_MESSAGING_SERVICE_SID
TWILIO_USE_WHATSAPP
USE_PAYMENTS
VICTOROPS_ENABLED
WEBHOOKS_ENABLED
ZULIP_ENABLED
)

function insert_config() {
if grep -E "^$1 = " /config/local_settings.py &> /dev/null; then
sed -i -E "s|^$1 = .*\$|$1 = $2|" /config/local_settings.py
else
echo "$1 = $2" >> /config/local_settings.py
fi
}
if [[ ! -f "/config/local_settings.py" ]]; then
touch /config/local_settings.py
fi

if [[ -z ${SITE_ROOT} ]] && ! grep -q "^SITE_ROOT" /config/local_settings.py; then
echo "No SITE_ROOT provided, halting init"
Expand All @@ -88,37 +15,23 @@ elif [[ -z ${SITE_ROOT} ]] && grep -q "^SITE_ROOT" /config/local_settings.py; th
SITE_ROOT=$(grep -Po "^SITE_ROOT\s*=\s*\K(.*)" /config/local_settings.py | tr -d '"')
fi

if [[ ! -f "/config/local_settings.py" ]] || [[ "${REGENERATE_SETTINGS,,}" == "true" ]]; then
touch /config/local_settings.py
for CONF in "${HC_CONF[@]}"; do
if [[ -n "${!CONF}" ]]; then
if [[ "${!CONF}" == "True" ]] || [[ "${!CONF}" == "False" ]] || [[ "${!CONF:0:1}" == "[" ]]; then #booleans or arrays
insert_config "$CONF" "${!CONF}"
else
insert_config "$CONF" "\"${!CONF}\""
fi
fi
done
if [[ -n ${CSRF_TRUSTED_ORIGINS} ]]; then
insert_config "CSRF_TRUSTED_ORIGINS" "${CSRF_TRUSTED_ORIGINS}"
else
insert_config "CSRF_TRUSTED_ORIGINS" "[\"${SITE_ROOT}\"]"
fi
if [[ -n ${PING_BODY_LIMIT} ]]; then
insert_config "PING_BODY_LIMIT" "$(printf '%d\n' "${PING_BODY_LIMIT}")"
fi
# Need to inject SITE_ROOT into CSRF_TRUSTED_ORIGINS if not specified by the user because it defaults to an empty list
if [[ -z ${CSRF_TRUSTED_ORIGINS} ]] && ! grep -q "^CSRF_TRUSTED_ORIGINS" /config/local_settings.py; then
CSRF_TRUSTED_ORIGINS=[\"${SITE_ROOT}\"]
echo "${CSRF_TRUSTED_ORIGINS}" > /run/s6/container_environment/CSRF_TRUSTED_ORIGINS
fi

if [[ -z "$SECRET_KEY" ]] && ! grep "SECRET_KEY" /config/local_settings.py &> /dev/null; then
insert_config "SECRET_KEY" "\"$(tr -dc A-Za-z0-9 </dev/urandom | head -c 32; echo '')\""
if [[ -z ${SECRET_KEY} ]] && ! grep -q "^SECRET_KEY" /config/local_settings.py; then
SECRET_KEY=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 32; echo '')
echo "SECRET_KEY = \"${SECRET_KEY}\"" >> /config/local_settings.py
echo "*** No SECRET_KEY specified so a random one has been generated an written to /config/local_settings.py **"
fi


if [[ ! -f "/app/healthchecks/hc/local_settings.py" ]]; then
if [[ ! -L "/app/healthchecks/hc/local_settings.py" ]]; then
ln -s /config/local_settings.py /app/healthchecks/hc/local_settings.py
fi

if [[ ! -f "/app/healthchecks/hc.sqlite" ]]; then
if [[ ! -L "/app/healthchecks/hc.sqlite" ]]; then
ln -s /config/hc.sqlite /app/healthchecks/hc.sqlite
fi

Expand Down

0 comments on commit 71de43f

Please sign in to comment.