11#! /bin/sh
2+ set -e
3+ default_uid=0
4+ default_gid=0
5+ default_unprivileged_user=certbot
6+ default_unprivileged_group=certbot
7+
8+ if [ " $DEBUG " = " true" ]; then
9+ set -x
10+ fi
211
312# ###############################################################################
413# Functions
@@ -9,6 +18,41 @@ cleanup() {
918 exit 0
1019}
1120
21+ debug_print () {
22+ if [ " $DEBUG " = " true" ]; then
23+ echo " $1 "
24+ fi
25+ }
26+
27+ configure_uid_and_gid () {
28+ debug_print " Preparing environment for $PUID :$PGID ..."
29+
30+ # Handle existing user with the same UID
31+ if id -u " ${PUID} " > /dev/null 2>&1 ; then
32+ old_user=$( id -nu " ${PUID} " )
33+ debug_print " UID ${PUID} already exists for user ${old_user} . Moving to a new UID."
34+ usermod -u " 999${PUID} " " ${old_user} "
35+ fi
36+
37+ # Handle existing group with the same GID
38+ if getent group " ${PGID} " > /dev/null 2>&1 ; then
39+ old_group=$( getent group " ${PGID} " | cut -d: -f1)
40+ debug_print " GID ${PGID} already exists for group ${old_group} . Moving to a new GID."
41+ groupmod -g " 999${PGID} " " ${old_group} "
42+ fi
43+
44+ # Change UID and GID of run_as user and group
45+ usermod -u " ${PUID} " " ${default_unprivileged_user} " 2>&1 > /dev/null || echo " Error changing user ID."
46+ groupmod -g " ${PGID} " " ${default_unprivileged_user} " 2>&1 > /dev/null || echo " Error changing group ID."
47+
48+ # Ensure the correct permissions are set for all required directories
49+ chown -R " ${default_unprivileged_user} :${default_unprivileged_group} " \
50+ /etc/letsencrypt \
51+ /var/lib/letsencrypt \
52+ /var/log/letsencrypt \
53+ /opt/certbot
54+ }
55+
1256configure_windows_file_permissions () {
1357 # Permissions must be created after volumes have been mounted; otherwise, windows file system permissions will override
1458 # the permissions set within the container.
@@ -40,8 +84,28 @@ replace_symlinks() {
4084 done
4185}
4286
87+ is_default_privileges () {
88+ [ " ${PUID:- $default_uid } " = " $default_uid " ] && [ " ${PGID:- $default_gid } " = " $default_gid " ]
89+ }
90+
4391run_certbot () {
44- certbot certonly \
92+ # Ensure the log directory is set to 700
93+ chmod 700 /var/log/letsencrypt
94+ chown " ${PUID} :${PGID} " /var/log/letsencrypt
95+
96+ if is_default_privileges; then
97+ certbot_cmd=" certbot"
98+ else
99+ certbot_cmd=" su-exec ${default_unprivileged_user} certbot"
100+ fi
101+
102+ debug_print " Running certbot with command: $certbot_cmd "
103+
104+ # Add -v flag if DEBUG is enabled
105+ debug_flag=" "
106+ [ " $DEBUG " = " true" ] && debug_flag=" -v"
107+
108+ $certbot_cmd $debug_flag certonly \
45109 --dns-cloudflare \
46110 --dns-cloudflare-credentials /cloudflare.ini \
47111 -d " $CERTBOT_DOMAINS " \
@@ -79,6 +143,10 @@ trap cleanup TERM INT
79143
80144validate_environment_variables
81145
146+ if ! is_default_privileges; then
147+ configure_uid_and_gid
148+ fi
149+
82150if [ " $REPLACE_SYMLINKS " = " true" ]; then
83151 configure_windows_file_permissions
84152fi
@@ -110,32 +178,44 @@ echo "-----------------------------------------------------------"
110178# Create Cloudflare configuration file
111179echo " dns_cloudflare_api_token = $CLOUDFLARE_API_TOKEN " > /cloudflare.ini
112180chmod 600 /cloudflare.ini
181+ if ! is_default_privileges; then
182+ chown " ${PUID} :${PGID} " /cloudflare.ini
183+ fi
113184
114- # Run certbot initially to get the certificates
115- run_certbot
116-
117- # Infinite loop to keep the container running and periodically check for renewals
118- while true ; do
119- # POSIX-compliant way to show next run time
120- current_timestamp=$( date +%s)
121- next_timestamp=$(( current_timestamp + RENEWAL_INTERVAL))
122- next_run=$( date -r " $next_timestamp " ' +%Y-%m-%d %H:%M:%S %z' 2> /dev/null || date ' +%Y-%m-%d %H:%M:%S %z' )
123- echo " Next certificate renewal check will be at ${next_run} "
124-
125- # Store PID of sleep process and wait for it
126- sleep " $RENEWAL_INTERVAL " &
127- sleep_pid=$!
128- wait $sleep_pid
129- wait_status=$?
130-
131- # Check if we received a signal (more portable check)
132- case $wait_status in
133- 0) : ;; # Normal exit
134- * ) cleanup ;;
135- esac
136-
137- if ! run_certbot; then
138- echo " Error: Certificate renewal failed. Exiting."
139- exit 1
185+ # Check if a command was passed to the container
186+ if [ $# -gt 0 ]; then
187+ if is_default_privileges; then
188+ exec " $@ "
189+ else
190+ exec su-exec " ${default_unprivileged_user} " " $@ "
140191 fi
141- done
192+ else
193+ # Run certbot initially to get the certificates
194+ run_certbot
195+
196+ # Infinite loop to keep the container running and periodically check for renewals
197+ while true ; do
198+ # POSIX-compliant way to show next run time
199+ current_timestamp=$( date +%s)
200+ next_timestamp=$(( current_timestamp + RENEWAL_INTERVAL))
201+ next_run=$( date -r " $next_timestamp " ' +%Y-%m-%d %H:%M:%S %z' 2> /dev/null || date ' +%Y-%m-%d %H:%M:%S %z' )
202+ echo " Next certificate renewal check will be at ${next_run} "
203+
204+ # Store PID of sleep process and wait for it
205+ sleep " $RENEWAL_INTERVAL " &
206+ sleep_pid=$!
207+ wait $sleep_pid
208+ wait_status=$?
209+
210+ # Check if we received a signal (more portable check)
211+ case $wait_status in
212+ 0) : ;; # Normal exit
213+ * ) cleanup ;;
214+ esac
215+
216+ if ! run_certbot; then
217+ echo " Error: Certificate renewal failed. Exiting."
218+ exit 1
219+ fi
220+ done
221+ fi
0 commit comments